
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>正则表达式HOWTO &#8212; Python 3.7.3 文档</title>
    <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>
    <script type="text/javascript" src="../_static/translations.js"></script>
    
    <script type="text/javascript" src="../_static/sidebar.js"></script>
    
    <link rel="search" type="application/opensearchdescription+xml"
          title="在 Python 3.7.3 文档 中搜索"
          href="../_static/opensearch.xml"/>
    <link rel="author" title="关于这些文档" href="../about.html" />
    <link rel="index" title="索引" href="../genindex.html" />
    <link rel="search" title="搜索" href="../search.html" />
    <link rel="copyright" title="版权所有" href="../copyright.html" />
    <link rel="next" title="套接字编程指南" href="sockets.html" />
    <link rel="prev" title="日志操作手册" href="logging-cookbook.html" />
    <link rel="shortcut icon" type="image/png" href="../_static/py.png" />
    <link rel="canonical" href="https://docs.python.org/3/howto/regex.html" />
    
    <script type="text/javascript" src="../_static/copybutton.js"></script>
    <script type="text/javascript" src="../_static/switchers.js"></script>
    
    
    
    <style>
      @media only screen {
        table.full-width-table {
            width: 100%;
        }
      }
    </style>
 

  </head><body>  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             accesskey="I">索引</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python 模块索引"
             >模块</a> |</li>
        <li class="right" >
          <a href="sockets.html" title="套接字编程指南"
             accesskey="N">下一页</a> |</li>
        <li class="right" >
          <a href="logging-cookbook.html" title="日志操作手册"
             accesskey="P">上一页</a> |</li>
        <li><img src="../_static/py.png" alt=""
                 style="vertical-align: middle; margin-top: -1px"/></li>
        <li><a href="https://www.python.org/">Python</a> &#187;</li>
        <li>
          <span class="language_switcher_placeholder">zh_CN</span>
          <span class="version_switcher_placeholder">3.7.3</span>
          <a href="../index.html">文档</a> &#187;
        </li>

          <li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python 常用指引</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="快速搜索" type="text" name="q" />
          <input type="submit" value="转向" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>    

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="regular-expression-howto">
<span id="regex-howto"></span><h1>正则表达式HOWTO<a class="headerlink" href="#regular-expression-howto" title="永久链接至标题">¶</a></h1>
<table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field-odd field"><th class="field-name">作者:</th><td class="field-body">A.M. Kuchling &lt;<a class="reference external" href="mailto:amk&#37;&#52;&#48;amk&#46;ca">amk<span>&#64;</span>amk<span>&#46;</span>ca</a>&gt;</td>
</tr>
</tbody>
</table>
<div class="topic">
<p class="topic-title first">摘要</p>
<p>本文档是在Python中使用 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块使用正则表达式的入门教程。 它提供了比“标准库参考”中相应部分更平和的介绍。</p>
</div>
<div class="section" id="introduction">
<h2>概述<a class="headerlink" href="#introduction" title="永久链接至标题">¶</a></h2>
<p>正则表达式（称为RE，或正则，或正则表达式模式）本质上是嵌入在Python中的一种微小的、高度专业化的编程语言，可通过 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块获得。 使用这种小语言，你可以为要匹配的可能字符串集指定规则；此集可能包含英语句子，电子邮件地址，TeX命令或你喜欢的任何内容。 然后，您可以询问诸如“此字符串是否与模式匹配？”或“此字符串中的模式是否匹配？”等问题。 你还可以使用正则修改字符串或以各种方式将其拆分。</p>
<p>正则表达式模式被编译成一系列字节码，然后由用 C 编写的匹配引擎执行。对于高级用途，可能需要特别注意引擎如何执行给定的正则，并将正则写入以某种方式生成运行速度更快的字节码。 本文档未涉及优化，因为它要求你充分了解匹配引擎的内部结构。</p>
<p>正则表达式语言相对较小且受限制，因此并非所有可能的字符串处理任务都可以使用正则表达式完成。 还有一些任务 <em>可以</em> 用正则表达式完成，但表达式变得非常复杂。 在这些情况下，你最好编写 Python 代码来进行处理；虽然 Python 代码比精心设计的正则表达式慢，但它也可能更容易理解。</p>
</div>
<div class="section" id="simple-patterns">
<h2>简单模式<a class="headerlink" href="#simple-patterns" title="永久链接至标题">¶</a></h2>
<p>我们首先要了解最简单的正则表达式。 由于正则表达式用于对字符串进行操作，因此我们将从最常见的任务开始：匹配字符。</p>
<p>有关正则表达式（确定性和非确定性有限自动机）的计算机科学的详细解释，你可以参考几乎所有有关编写编译器的教科书。</p>
<div class="section" id="matching-characters">
<h3>匹配字符<a class="headerlink" href="#matching-characters" title="永久链接至标题">¶</a></h3>
<p>大多数字母和字符只会匹配自己。 例如，正则表达式 <code class="docutils literal notranslate"><span class="pre">test</span></code> 将完全匹配字符串 <code class="docutils literal notranslate"><span class="pre">test</span></code> 。 （你可以启用一个不区分大小写的模式，让这个正则匹配 <code class="docutils literal notranslate"><span class="pre">Test</span></code> 或 <code class="docutils literal notranslate"><span class="pre">TEST</span></code>，稍后会详细介绍。）</p>
<p>这条规则有例外；一些字符是特殊的 <em class="dfn">metacharacters</em> ，并且不匹配自己。 相反，它们表示应该匹配一些与众不同的东西，或者通过重复它们或改变它们的含义来影响正则的其他部分。 本文档的大部分内容都致力于讨论各种元字符及其功能。</p>
<p>这是元字符的完整列表；它们的意思将在本HOWTO的其余部分讨论。</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>. ^ $ * + ? { } [ ] \ | ( )
</pre></div>
</div>
<p>我们将看到的第一个元字符是 <code class="docutils literal notranslate"><span class="pre">[``和</span></code>]``。 它们用于指定字符类，它是你希望匹配的一组字符。 可以单独列出字符，也可以通过给出两个字符并用 <code class="docutils literal notranslate"><span class="pre">'-'</span></code> 标记将它们分开来表示一系列字符。 例如，<code class="docutils literal notranslate"><span class="pre">[abc]</span></code> 将匹配任何字符 <code class="docutils literal notranslate"><span class="pre">a</span></code>、<code class="docutils literal notranslate"><span class="pre">b</span></code> 或 <code class="docutils literal notranslate"><span class="pre">c</span></code>; 这与 <code class="docutils literal notranslate"><span class="pre">[a-c]</span></code> 相同，它使用一个范围来表示同一组字符。 如果你只想匹配小写字母，你的正则是 <code class="docutils literal notranslate"><span class="pre">[a-z]</span></code>。</p>
<p>字符类中的元字符不生效。 例如，<code class="docutils literal notranslate"><span class="pre">[akm$]</span></code> 将匹配``'a'<code class="docutils literal notranslate"><span class="pre">，</span></code>'k'<code class="docutils literal notranslate"><span class="pre">、</span></code>'m'<code class="docutils literal notranslate"><span class="pre">或</span></code>'$'`` 中的任意字符；<code class="docutils literal notranslate"><span class="pre">'$'</span></code> 通常是一个元字符，但在一个字符类中它被剥夺了特殊性。</p>
<p>你可以通过以下方式匹配 <em class="dfn">complementing</em> 设置的字符类中未列出的字符。这通过包含一个 <code class="docutils literal notranslate"><span class="pre">'^'</span></code> 作为该类的第一个字符来表示。 例如，<code class="docutils literal notranslate"><span class="pre">[^5]</span></code> 将匹配除 <code class="docutils literal notranslate"><span class="pre">'5'</span></code> 之外的任何字符。 如果插入符出现在字符类的其他位置，则它没有特殊含义。 例如：<code class="docutils literal notranslate"><span class="pre">[5^]</span></code> 将匹配 <code class="docutils literal notranslate"><span class="pre">'5'</span></code> 或 <code class="docutils literal notranslate"><span class="pre">'^'</span></code>。</p>
<p>也许最重要的元字符是反斜杠，<code class="docutils literal notranslate"><span class="pre">\</span></code>。 与 Python 字符串文字一样，反斜杠后面可以跟各种字符，以指示各种特殊序列。它也用于转义所有元字符，因此您仍然可以在模式中匹配它们；例如，如果你需要匹配 <code class="docutils literal notranslate"><span class="pre">[</span></code> 或 <code class="docutils literal notranslate"><span class="pre">\</span></code>，你可以在它们前面加一个反斜杠来移除它们的特殊含义：<code class="docutils literal notranslate"><span class="pre">\[</span></code> 或 <code class="docutils literal notranslate"><span class="pre">\\</span></code>。</p>
<p>一些以 <code class="docutils literal notranslate"><span class="pre">'\'</span></code> 开头的特殊序列表示通常有用的预定义字符集，例如数字集、字母集或任何非空格的集合。</p>
<p>让我们举一个例子：<code class="docutils literal notranslate"><span class="pre">\w</span></code> 匹配任何字母数字字符。 如果正则表达式模式以字节类表示，这相当于类 <code class="docutils literal notranslate"><span class="pre">[a-zA-Z0-9_]</span></code>。如果正则表达式是一个字符串，<code class="docutils literal notranslate"><span class="pre">\w</span></code> 将匹配由 <a class="reference internal" href="../library/unicodedata.html#module-unicodedata" title="unicodedata: Access the Unicode Database."><code class="xref py py-mod docutils literal notranslate"><span class="pre">unicodedata</span></code></a> 模块提供的 Unicode 数据库中标记为字母的所有字符。 通过在编译正则表达式时提供 <a class="reference internal" href="../library/re.html#re.ASCII" title="re.ASCII"><code class="xref py py-const docutils literal notranslate"><span class="pre">re.ASCII</span></code></a> 标志，可以在字符串模式中使用更为受限制的 <code class="docutils literal notranslate"><span class="pre">\w</span></code> 定义。</p>
<p>以下特殊序列列表不完整。 有关 Unicode 字符串模式的序列和扩展类定义的完整列表，请参阅标准库参考中的最后一部分 <a class="reference internal" href="../library/re.html#re-syntax"><span class="std std-ref">正则表达式语法</span></a> 。通常，Unicode 版本匹配 Unicode 数据库中相应类别中的任何字符。</p>
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">\d</span></code></dt>
<dd>匹配任何十进制数字；这等价于类 <code class="docutils literal notranslate"><span class="pre">[0-9]</span></code>。</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\D</span></code></dt>
<dd>匹配任何非数字字符；这等价于类 <code class="docutils literal notranslate"><span class="pre">[^0-9]</span></code>。</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\s</span></code></dt>
<dd>匹配任何空白字符；这等价于类 <code class="docutils literal notranslate"><span class="pre">[</span> <span class="pre">\t\n\r\f\v]</span></code>。</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\S</span></code></dt>
<dd>匹配任何非空白字符；这相当于类 <code class="docutils literal notranslate"><span class="pre">[^</span> <span class="pre">\t\n\r\f\v]</span></code>。</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\w</span></code></dt>
<dd>匹配任何字母与数字字符；这相当于类 <code class="docutils literal notranslate"><span class="pre">[a-zA-Z0-9_]</span></code>。</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\W</span></code></dt>
<dd>匹配任何非字母与数字字符；这相当于类 <code class="docutils literal notranslate"><span class="pre">[^a-zA-Z0-9_]</span></code>。</dd>
</dl>
<p>这些序列可以包含在字符类中。 例如，<code class="docutils literal notranslate"><span class="pre">[\s,.]</span></code> 是一个匹配任何空格字符的字符类或者 <code class="docutils literal notranslate"><span class="pre">','</span></code> ，或 <code class="docutils literal notranslate"><span class="pre">'.'</span></code>。</p>
<p>本节的最后一个元字符是 <code class="docutils literal notranslate"><span class="pre">.</span></code> 。 它匹配除换行符之外的任何内容，并且有一个可选模式（ <a class="reference internal" href="../library/re.html#re.DOTALL" title="re.DOTALL"><code class="xref py py-const docutils literal notranslate"><span class="pre">re.DOTALL</span></code></a> ）甚至可以匹配换行符。 <code class="docutils literal notranslate"><span class="pre">.</span></code> 常用于你想匹配“任何字符”的地方。</p>
</div>
<div class="section" id="repeating-things">
<h3>重复<a class="headerlink" href="#repeating-things" title="永久链接至标题">¶</a></h3>
<p>能够匹配不同的字符集合是正则表达式可以做的第一件事，这对于字符串可用方法来说是不可能的。 但是，如果这是正则表达式的唯一额外功能，那么它们就不会有太大的优势。 另一个功能是你可以指定正则的某些部分必须重复一定次数。</p>
<p>重复中我们要了解的第一个元字符是 <code class="docutils literal notranslate"><span class="pre">*</span></code>。 <code class="docutils literal notranslate"><span class="pre">*</span></code> 与字面字符 <code class="docutils literal notranslate"><span class="pre">'*'</span></code> 不匹配；相反，它指定前一个字符可以匹配零次或多次，而不是恰好一次。</p>
<p>例如，<code class="docutils literal notranslate"><span class="pre">ca*t</span></code> 将匹配 <code class="docutils literal notranslate"><span class="pre">'ct'</span></code> (0个 <code class="docutils literal notranslate"><span class="pre">'a'</span></code> 字符)，<code class="docutils literal notranslate"><span class="pre">'cat'</span></code> (1个``'a'<code class="docutils literal notranslate"><span class="pre">)，`</span> <span class="pre">`'caaat'</span></code> (3个 <code class="docutils literal notranslate"><span class="pre">'a'</span></code> 字符)，等等。</p>
<p>类似 <code class="docutils literal notranslate"><span class="pre">*</span></code> 这样的重复是 <em class="dfn">贪婪的</em>；当重复正则时，匹配引擎将尝试尽可能多地重复它。 如果模式的后续部分不匹配，则匹配引擎将回退并以较少的重复次数再次尝试。</p>
<p>一个逐步的例子将使这更加明显。 让我们考虑表达式 <code class="docutils literal notranslate"><span class="pre">a[bcd]*b</span></code>。 这个正则匹配字母 <code class="docutils literal notranslate"><span class="pre">'a'</span></code>，类 <code class="docutils literal notranslate"><span class="pre">[bcd]</span></code> 中的零或多个字母，最后以 <code class="docutils literal notranslate"><span class="pre">'b'</span></code> 结尾。 现在想象一下这个正则与字符串 <code class="docutils literal notranslate"><span class="pre">'abcbd'</span></code> 匹配。</p>
<table border="1" class="docutils">
<colgroup>
<col width="12%" />
<col width="22%" />
<col width="66%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">步骤</th>
<th class="head">匹配</th>
<th class="head">解释</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>1</td>
<td><code class="docutils literal notranslate"><span class="pre">a</span></code></td>
<td>正则中的 <code class="docutils literal notranslate"><span class="pre">a</span></code> 匹配。</td>
</tr>
<tr class="row-odd"><td>2</td>
<td><code class="docutils literal notranslate"><span class="pre">abcbd</span></code></td>
<td>引擎尽可能多地匹配 <code class="docutils literal notranslate"><span class="pre">[bcd]*</span></code> ，直到字符串结束。</td>
</tr>
<tr class="row-even"><td>3</td>
<td><em>失败</em></td>
<td>引擎尝试匹配 <code class="docutils literal notranslate"><span class="pre">b</span></code> ，但是当前位置位于字符串结束，所以匹配失败。</td>
</tr>
<tr class="row-odd"><td>4</td>
<td><code class="docutils literal notranslate"><span class="pre">abcb</span></code></td>
<td>回退一次，<code class="docutils literal notranslate"><span class="pre">[bcd]*</span></code> 少匹配一个字符。</td>
</tr>
<tr class="row-even"><td>5</td>
<td><em>失败</em></td>
<td>再次尝试匹配 <code class="docutils literal notranslate"><span class="pre">b</span></code> ， 但是当前位置是最后一个字符 <code class="docutils literal notranslate"><span class="pre">'d'</span></code> 。</td>
</tr>
<tr class="row-odd"><td>6</td>
<td><code class="docutils literal notranslate"><span class="pre">abc</span></code></td>
<td>再次回退，所以 <code class="docutils literal notranslate"><span class="pre">[bcd]*</span></code> 只匹配 <code class="docutils literal notranslate"><span class="pre">bc</span></code> 。</td>
</tr>
<tr class="row-even"><td>6</td>
<td><code class="docutils literal notranslate"><span class="pre">abcb</span></code></td>
<td>再试一次 <code class="docutils literal notranslate"><span class="pre">b</span></code> 。 这次当前位置的字符是 <code class="docutils literal notranslate"><span class="pre">'b'</span></code> ，所以它成功了。</td>
</tr>
</tbody>
</table>
<p>正则现在已经结束了，它已经匹配了 <code class="docutils literal notranslate"><span class="pre">'abcb'</span></code>。 这演示了匹配引擎最初如何进行，如果没有找到匹配，它将逐步回退并一次又一次地重试正则的其余部分。 它将回退，直到它为 <code class="docutils literal notranslate"><span class="pre">[bcd]*</span></code> 尝试零匹配，如果随后失败，引擎将断定该字符串与正则完全不匹配。</p>
<p>另一个重复的元字符是 <code class="docutils literal notranslate"><span class="pre">+</span></code>，它匹配一次或多次。 要特别注意 <code class="docutils literal notranslate"><span class="pre">*</span></code> 和 <code class="docutils literal notranslate"><span class="pre">+</span></code> 之间的区别；<code class="docutils literal notranslate"><span class="pre">*</span></code> 匹配 <em>零次</em> 或更多次，因此重复的任何东西都可能根本不存在，而 <code class="docutils literal notranslate"><span class="pre">+</span></code> 至少需要 <em>一次</em>。 使用类似的例子，<code class="docutils literal notranslate"><span class="pre">ca+t</span></code> 将匹配 <code class="docutils literal notranslate"><span class="pre">'cat'</span></code> (1 个 <code class="docutils literal notranslate"><span class="pre">'a'</span></code>)，<code class="docutils literal notranslate"><span class="pre">'caaat'</span></code> (3 个 <code class="docutils literal notranslate"><span class="pre">'a'</span></code>)，但不会匹配 <code class="docutils literal notranslate"><span class="pre">'ct'</span></code>。</p>
<p>还有两个重复限定符。 问号字符 <code class="docutils literal notranslate"><span class="pre">?</span></code> 匹配一次或零次；你可以把它想象成是可选的。 例如，<code class="docutils literal notranslate"><span class="pre">home-?brew</span></code> 匹配 <code class="docutils literal notranslate"><span class="pre">'homebrew'</span></code> 或 <code class="docutils literal notranslate"><span class="pre">'home-brew'</span></code>。</p>
<p>最复杂的重复限定符是 <code class="docutils literal notranslate"><span class="pre">{m,n}</span></code>，其中 <em>m</em> 和 <em>n</em> 是十进制整数。 这个限定符意味着必须至少重复 <em>m</em> 次，最多重复 <em>n</em> 次。 例如，<code class="docutils literal notranslate"><span class="pre">a/{1,3}b</span></code> 将匹配 <code class="docutils literal notranslate"><span class="pre">'a/b'</span></code> ，<code class="docutils literal notranslate"><span class="pre">'a//b'</span></code> 和 <code class="docutils literal notranslate"><span class="pre">'a///b'</span></code> 。 它不匹配没有斜线的 <code class="docutils literal notranslate"><span class="pre">'ab'</span></code>，或者有四个的 <code class="docutils literal notranslate"><span class="pre">'a////b'</span></code>。</p>
<p>你可以省略 <em>m</em> 或 <em>n</em>; 在这种情况下，将假定缺失值的合理值。 省略 <em>m</em> 被解释为 0 下限，而省略 <em>n</em> 则为无穷大的上限。</p>
<p>还原论者的读者可能会注意到其他三个限定符都可以用这种表示法表达。 <code class="docutils literal notranslate"><span class="pre">{0,}``与``*``相同，``{1,}``相当于``+</span></code>，<code class="docutils literal notranslate"><span class="pre">{0,1}``和</span></code>?``相同。 最好使用``*``，<code class="docutils literal notranslate"><span class="pre">+``或</span></code>?``，只要因为它们更短更容易阅读。</p>
</div>
</div>
<div class="section" id="using-regular-expressions">
<h2>使用正则表达式<a class="headerlink" href="#using-regular-expressions" title="永久链接至标题">¶</a></h2>
<p>现在我们已经看了一些简单的正则表达式，我们如何在 Python 中实际使用它们？ <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块提供了正则表达式引擎的接口，允许你将正则编译为对象，然后用它们进行匹配。</p>
<div class="section" id="compiling-regular-expressions">
<h3>编译正则表达式<a class="headerlink" href="#compiling-regular-expressions" title="永久链接至标题">¶</a></h3>
<p>正则表达式被编译成模式对象，模式对象具有各种操作的方法，例如搜索模式匹配或执行字符串替换。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">re</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;ab*&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span>
<span class="go">re.compile(&#39;ab*&#39;)</span>
</pre></div>
</div>
<p><a class="reference internal" href="../library/re.html#re.compile" title="re.compile"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.compile()</span></code></a> 也接受一个可选的 <em>flags</em> 参数，用于启用各种特殊功能和语法变体。 我们稍后将介绍可用的设置，但现在只需一个例子</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;ab*&#39;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">IGNORECASE</span><span class="p">)</span>
</pre></div>
</div>
<p>正则作为字符串传递给 <a class="reference internal" href="../library/re.html#re.compile" title="re.compile"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.compile()</span></code></a> 。 正则被处理为字符串，因为正则表达式不是核心Python语言的一部分，并且没有创建用于表达它们的特殊语法。 （有些应用程序根本不需要正则，因此不需要通过包含它们来扩展语言规范。）相反，<a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块只是Python附带的C扩展模块，就类似于 <a class="reference internal" href="../library/socket.html#module-socket" title="socket: Low-level networking interface."><code class="xref py py-mod docutils literal notranslate"><span class="pre">socket</span></code></a> 或 <a class="reference internal" href="../library/zlib.html#module-zlib" title="zlib: Low-level interface to compression and decompression routines compatible with gzip."><code class="xref py py-mod docutils literal notranslate"><span class="pre">zlib</span></code></a> 模块。</p>
<p>将正则放在字符串中可以使 Python 语言更简单，但有一个缺点是下一节的主题。</p>
</div>
<div class="section" id="the-backslash-plague">
<span id="id1"></span><h3>反斜杠灾难<a class="headerlink" href="#the-backslash-plague" title="永久链接至标题">¶</a></h3>
<p>如前所述，正则表达式使用反斜杠字符 (<code class="docutils literal notranslate"><span class="pre">'\'</span></code>) 来表示特殊形式或允许使用特殊字符而不调用它们的特殊含义。 这与 Python 在字符串文字中用于相同目的的相同字符的使用相冲突。</p>
<p>假设你想要编写一个与字符串 <code class="docutils literal notranslate"><span class="pre">\section</span></code> 相匹配的正则，它可以在 LaTeX 文件中找到。 要找出在程序代码中写入的内容，请从要匹配的字符串开始。 接下来，您必须通过在反斜杠前面添加反斜杠和其他元字符，从而产生字符串 <code class="docutils literal notranslate"><span class="pre">\\section</span></code>。 必须传递给 <a class="reference internal" href="../library/re.html#re.compile" title="re.compile"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.compile()</span></code></a> 的结果字符串必须是 <code class="docutils literal notranslate"><span class="pre">\\section</span></code>。 但是，要将其表示为 Python 字符串文字，必须 <em>再次</em> 转义两个反斜杠。</p>
<table border="1" class="docutils">
<colgroup>
<col width="31%" />
<col width="69%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">字符</th>
<th class="head">阶段</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">\section</span></code></td>
<td>被匹配的字符串</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">\\section</span></code></td>
<td>为 <a class="reference internal" href="../library/re.html#re.compile" title="re.compile"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.compile()</span></code></a> 转义的反斜杠</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">&quot;\\\\section&quot;</span></code></td>
<td>为字符串字面转义的反斜杠</td>
</tr>
</tbody>
</table>
<p>简而言之，要匹配文字反斜杠，必须将 <code class="docutils literal notranslate"><span class="pre">'\\\\'</span></code> 写为正则字符串，因为正则表达式必须是 <code class="docutils literal notranslate"><span class="pre">\\</span></code>，并且每个反斜杠必须表示为 <code class="docutils literal notranslate"><span class="pre">\\</span></code> 在常规Python字符串字面中。 在反复使用反斜杠的正则中，这会导致大量重复的反斜杠，并使得生成的字符串难以理解。</p>
<p>解决方案是使用 Python 的原始字符串表示法来表示正则表达式；反斜杠不以任何特殊的方式处理前缀为 <code class="docutils literal notranslate"><span class="pre">'r'</span></code> 的字符串字面，因此 <code class="docutils literal notranslate"><span class="pre">r&quot;\n&quot;</span></code> 是一个包含 <code class="docutils literal notranslate"><span class="pre">'\'</span></code> 和 <code class="docutils literal notranslate"><span class="pre">'n'</span></code> 的双字符字符串，而 <code class="docutils literal notranslate"><span class="pre">&quot;\n&quot;</span></code> 是一个包含换行符的单字符字符串。 正则表达式通常使用这种原始字符串表示法用 Python 代码编写。</p>
<p>此外，在正则表达式中有效但在 Python 字符串文字中无效的特殊转义序列现在导致 <a class="reference internal" href="../library/exceptions.html#DeprecationWarning" title="DeprecationWarning"><code class="xref py py-exc docutils literal notranslate"><span class="pre">DeprecationWarning</span></code></a> 并最终变为 <a class="reference internal" href="../library/exceptions.html#SyntaxError" title="SyntaxError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">SyntaxError</span></code></a>。 这意味着如果未使用原始字符串表示法或转义反斜杠，序列将无效。</p>
<table border="1" class="docutils">
<colgroup>
<col width="51%" />
<col width="49%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">常规字符串</th>
<th class="head">原始字符串</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">&quot;ab*&quot;</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">r&quot;ab*&quot;</span></code></td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">&quot;\\\\section&quot;</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">r&quot;\\section&quot;</span></code></td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">&quot;\\w+\\s+\\1&quot;</span></code></td>
<td><code class="docutils literal notranslate"><span class="pre">r&quot;\w+\s+\1&quot;</span></code></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="performing-matches">
<h3>应用匹配<a class="headerlink" href="#performing-matches" title="永久链接至标题">¶</a></h3>
<p>一旦你有一个表示编译正则表达式的对象，你用它做什么？ 模式对象有几种方法和属性。 这里只介绍最重要的内容；请参阅 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 文档获取完整列表。</p>
<table border="1" class="docutils">
<colgroup>
<col width="28%" />
<col width="72%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">方法 / 属性</th>
<th class="head">目的</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">match()</span></code></td>
<td>确定正则是否从字符串的开头匹配。</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">search()</span></code></td>
<td>扫描字符串，查找此正则匹配的任何位置。</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">findall()</span></code></td>
<td>找到正则匹配的所有子字符串，并将它们作为列表返回。</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">finditer()</span></code></td>
<td>找到正则匹配的所有子字符串，并将它们返回为一个 <a class="reference internal" href="../glossary.html#term-iterator"><span class="xref std std-term">iterator</span></a>。</td>
</tr>
</tbody>
</table>
<p>如果没有找到匹配， <a class="reference internal" href="../library/re.html#re.Pattern.match" title="re.Pattern.match"><code class="xref py py-meth docutils literal notranslate"><span class="pre">match()</span></code></a> 和 <a class="reference internal" href="../library/re.html#re.Pattern.search" title="re.Pattern.search"><code class="xref py py-meth docutils literal notranslate"><span class="pre">search()</span></code></a> 返回 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。如果它们成功， 一个 <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a> 实例将被返回，包含匹配相关的信息：起始和终结位置、匹配的子串以及其它。</p>
<p>你可以通过交互式实验 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块来了解这一点。 如果你有 <a class="reference internal" href="../library/tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><code class="xref py py-mod docutils literal notranslate"><span class="pre">tkinter</span></code></a>，你可能还想查看 <a class="reference external" href="https://github.com/python/cpython/tree/3.7/Tools/demo/redemo.py">Tools/demo/redemo.py</a>，这是 Python 发行附带的演示程序。 它允许你输入正则和字符串，并显示RE是匹配还是失败。  <code class="file docutils literal notranslate"><span class="pre">redemo.py</span></code> 在尝试调试复杂的正则时非常有用。</p>
<p>本 HOWTO 使用标准 Python 解释器作为示例。 首先，运行 Python 解释器，导入 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块，然后编译一个正则</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">re</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;[a-z]+&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span>
<span class="go">re.compile(&#39;[a-z]+&#39;)</span>
</pre></div>
</div>
<p>现在，你可以尝试匹配正则 <code class="docutils literal notranslate"><span class="pre">[a-z]+</span></code> 的各种字符串。 空字符串根本不匹配，因为 <code class="docutils literal notranslate"><span class="pre">+</span></code> 表示“一次或多次重复”。 <a class="reference internal" href="../library/re.html#re.Pattern.match" title="re.Pattern.match"><code class="xref py py-meth docutils literal notranslate"><span class="pre">match()</span></code></a> 在这种情况下应返回 <code class="docutils literal notranslate"><span class="pre">None</span></code>，这将导致解释器不打印输出。 你可以显式打印 <code class="xref py py-meth docutils literal notranslate"><span class="pre">match()</span></code> 的结果，使其清晰。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">))</span>
<span class="go">None</span>
</pre></div>
</div>
<p>现在，让我们尝试一下它应该匹配的字符串，例如 <code class="docutils literal notranslate"><span class="pre">tempo</span></code>。在这个例子中 <a class="reference internal" href="../library/re.html#re.Pattern.match" title="re.Pattern.match"><code class="xref py py-meth docutils literal notranslate"><span class="pre">match()</span></code></a> 将返回一个 <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a>，因此你应该将结果储存到一个变量中以供稍后使用。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;tempo&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span>
<span class="go">&lt;re.Match object; span=(0, 5), match=&#39;tempo&#39;&gt;</span>
</pre></div>
</div>
<p>现在你可以检查 <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a> 以获取有关匹配字符串的信息。 匹配对象实例也有几个方法和属性；最重要的是：</p>
<table border="1" class="docutils">
<colgroup>
<col width="29%" />
<col width="71%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">方法 / 属性</th>
<th class="head">目的</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">group()</span></code></td>
<td>返回正则匹配的字符串</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">start()</span></code></td>
<td>返回匹配的开始位置</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">end()</span></code></td>
<td>返回匹配的结束位置</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">span()</span></code></td>
<td>返回包含匹配 (start, end) 位置的元组</td>
</tr>
</tbody>
</table>
<p>尝试这些方法很快就会清楚它们的含义:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
<span class="go">&#39;tempo&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">start</span><span class="p">(),</span> <span class="n">m</span><span class="o">.</span><span class="n">end</span><span class="p">()</span>
<span class="go">(0, 5)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">span</span><span class="p">()</span>
<span class="go">(0, 5)</span>
</pre></div>
</div>
<p><a class="reference internal" href="../library/re.html#re.Match.group" title="re.Match.group"><code class="xref py py-meth docutils literal notranslate"><span class="pre">group()</span></code></a> 返回正则匹配的子字符串。 <a class="reference internal" href="../library/re.html#re.Match.start" title="re.Match.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a> 和 <a class="reference internal" href="../library/re.html#re.Match.end" title="re.Match.end"><code class="xref py py-meth docutils literal notranslate"><span class="pre">end()</span></code></a> 返回匹配的起始和结束索引。 <a class="reference internal" href="../library/re.html#re.Match.span" title="re.Match.span"><code class="xref py py-meth docutils literal notranslate"><span class="pre">span()</span></code></a> 在单个元组中返回开始和结束索引。 由于 <a class="reference internal" href="../library/re.html#re.Pattern.match" title="re.Pattern.match"><code class="xref py py-meth docutils literal notranslate"><span class="pre">match()</span></code></a> 方法只检查正则是否在字符串的开头匹配，所以 <code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code> 将始终为零。 但是，模式的 <a class="reference internal" href="../library/re.html#re.Pattern.search" title="re.Pattern.search"><code class="xref py py-meth docutils literal notranslate"><span class="pre">search()</span></code></a> 方法会扫描字符串，因此在这种情况下匹配可能不会从零开始。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;::: message&#39;</span><span class="p">))</span>
<span class="go">None</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;::: message&#39;</span><span class="p">);</span> <span class="nb">print</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
<span class="go">&lt;re.Match object; span=(4, 11), match=&#39;message&#39;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
<span class="go">&#39;message&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">span</span><span class="p">()</span>
<span class="go">(4, 11)</span>
</pre></div>
</div>
<p>在实际程序中，最常见的样式是在变量中存储 <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a>，然后检查它是否为 <code class="docutils literal notranslate"><span class="pre">None</span></code>。 这通常看起来像:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span> <span class="o">...</span> <span class="p">)</span>
<span class="n">m</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">match</span><span class="p">(</span> <span class="s1">&#39;string goes here&#39;</span> <span class="p">)</span>
<span class="k">if</span> <span class="n">m</span><span class="p">:</span>
    <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Match found: &#39;</span><span class="p">,</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">())</span>
<span class="k">else</span><span class="p">:</span>
    <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;No match&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>两种模式方法返回模式的所有匹配项。 <a class="reference internal" href="../library/re.html#re.Pattern.findall" title="re.Pattern.findall"><code class="xref py py-meth docutils literal notranslate"><span class="pre">findall()</span></code></a> 返回匹配字符串的列表:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\d+&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s1">&#39;12 drummers drumming, 11 pipers piping, 10 lords a-leaping&#39;</span><span class="p">)</span>
<span class="go">[&#39;12&#39;, &#39;11&#39;, &#39;10&#39;]</span>
</pre></div>
</div>
<p>在这个例子中需要 <code class="docutils literal notranslate"><span class="pre">r</span></code> 前缀，使字面为原始字符串字面，因为普通的“加工”字符串字面中的转义序列不能被 Python 识别为正则表达式，导致 <a class="reference internal" href="../library/exceptions.html#DeprecationWarning" title="DeprecationWarning"><code class="xref py py-exc docutils literal notranslate"><span class="pre">DeprecationWarning</span></code></a> 并最终产生 <a class="reference internal" href="../library/exceptions.html#SyntaxError" title="SyntaxError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">SyntaxError</span></code></a>。 请参阅 <a class="reference internal" href="#the-backslash-plague"><span class="std std-ref">反斜杠灾难</span></a>。</p>
<p><a class="reference internal" href="../library/re.html#re.Pattern.findall" title="re.Pattern.findall"><code class="xref py py-meth docutils literal notranslate"><span class="pre">findall()</span></code></a> 必须先创建整个列表才能返回结果。 <a class="reference internal" href="../library/re.html#re.Pattern.finditer" title="re.Pattern.finditer"><code class="xref py py-meth docutils literal notranslate"><span class="pre">finditer()</span></code></a> 方法将一个 <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a> 的序列返回为一个 <a class="reference internal" href="../glossary.html#term-iterator"><span class="xref std std-term">iterator</span></a></p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">iterator</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="s1">&#39;12 drummers drumming, 11 ... 10 ...&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">iterator</span>  
<span class="go">&lt;callable_iterator object at 0x...&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">iterator</span><span class="p">:</span>
<span class="gp">... </span>    <span class="nb">print</span><span class="p">(</span><span class="n">match</span><span class="o">.</span><span class="n">span</span><span class="p">())</span>
<span class="gp">...</span>
<span class="go">(0, 2)</span>
<span class="go">(22, 24)</span>
<span class="go">(29, 31)</span>
</pre></div>
</div>
</div>
<div class="section" id="module-level-functions">
<h3>模块级别函数<a class="headerlink" href="#module-level-functions" title="永久链接至标题">¶</a></h3>
<p>你不必创建模式对象并调用其方法；<a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块还提供了顶级函数 <a class="reference internal" href="../library/re.html#re.match" title="re.match"><code class="xref py py-func docutils literal notranslate"><span class="pre">match()</span></code></a>，<a class="reference internal" href="../library/re.html#re.search" title="re.search"><code class="xref py py-func docutils literal notranslate"><span class="pre">search()</span></code></a>，<a class="reference internal" href="../library/re.html#re.findall" title="re.findall"><code class="xref py py-func docutils literal notranslate"><span class="pre">findall()</span></code></a>，<a class="reference internal" href="../library/re.html#re.sub" title="re.sub"><code class="xref py py-func docutils literal notranslate"><span class="pre">sub()</span></code></a> 等等。 这些函数采用与相应模式方法相同的参数，并将正则字符串作为第一个参数添加，并仍然返回 <code class="docutils literal notranslate"><span class="pre">None</span></code> 或  <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a> 实例。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;From\s+&#39;</span><span class="p">,</span> <span class="s1">&#39;Fromage amk&#39;</span><span class="p">))</span>
<span class="go">None</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;From\s+&#39;</span><span class="p">,</span> <span class="s1">&#39;From amk Thu May 14 19:12:10 1998&#39;</span><span class="p">)</span>  
<span class="go">&lt;re.Match object; span=(0, 5), match=&#39;From &#39;&gt;</span>
</pre></div>
</div>
<p>本质上，这些函数只是为你创建一个模式对象，并在其上调用适当的方法。 它们还将编译对象存储在缓存中，因此使用相同的未来调用将不需要一次又一次地解析该模式。</p>
<p>你是否应该使用这些模块级函数，还是应该自己获取模式并调用其方法？ 如果你正在循环中访问正则表达式，预编译它将节省一些函数调用。 在循环之外，由于有内部缓存，没有太大区别。</p>
</div>
<div class="section" id="compilation-flags">
<h3>编译标志<a class="headerlink" href="#compilation-flags" title="永久链接至标题">¶</a></h3>
<p>编译标志允许你修改正则表达式的工作方式。 标志在 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块中有两个名称，长名称如 <code class="xref py py-const docutils literal notranslate"><span class="pre">IGNORECASE</span></code> 和一个简短的单字母形式，例如 <code class="xref py py-const docutils literal notranslate"><span class="pre">I</span></code>。 （如果你熟悉 Perl 的模式修饰符，则单字母形式使用和其相同的字母；例如， <a class="reference internal" href="../library/re.html#re.VERBOSE" title="re.VERBOSE"><code class="xref py py-const docutils literal notranslate"><span class="pre">re.VERBOSE</span></code></a> 的缩写形式为 <a class="reference internal" href="../library/re.html#re.X" title="re.X"><code class="xref py py-const docutils literal notranslate"><span class="pre">re.X</span></code></a>。）多个标志可以 通过按位或运算来指定它们；例如，<code class="docutils literal notranslate"><span class="pre">re.I</span> <span class="pre">|</span> <span class="pre">re.M</span></code> 设置 <code class="xref py py-const docutils literal notranslate"><span class="pre">I</span></code> 和 <code class="xref py py-const docutils literal notranslate"><span class="pre">M</span></code> 标志。</p>
<p>这是一个可用标志表，以及每个标志的更详细说明。</p>
<table border="1" class="docutils">
<colgroup>
<col width="43%" />
<col width="57%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">标志</th>
<th class="head">意义</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><code class="xref py py-const docutils literal notranslate"><span class="pre">ASCII</span></code>, <code class="xref py py-const docutils literal notranslate"><span class="pre">A</span></code></td>
<td>使几个转义如 <code class="docutils literal notranslate"><span class="pre">\w</span></code>、<code class="docutils literal notranslate"><span class="pre">\b</span></code>、<code class="docutils literal notranslate"><span class="pre">\s</span></code> 和 <code class="docutils literal notranslate"><span class="pre">\d</span></code> 匹配仅与具有相应特征属性的 ASCII 字符匹配。</td>
</tr>
<tr class="row-odd"><td><code class="xref py py-const docutils literal notranslate"><span class="pre">DOTALL</span></code>, <code class="xref py py-const docutils literal notranslate"><span class="pre">S</span></code></td>
<td>使 <code class="docutils literal notranslate"><span class="pre">.</span></code> 匹配任何字符，包括换行符。</td>
</tr>
<tr class="row-even"><td><code class="xref py py-const docutils literal notranslate"><span class="pre">IGNORECASE</span></code>, <code class="xref py py-const docutils literal notranslate"><span class="pre">I</span></code></td>
<td>进行大小写不敏感匹配。</td>
</tr>
<tr class="row-odd"><td><code class="xref py py-const docutils literal notranslate"><span class="pre">LOCALE</span></code>, <code class="xref py py-const docutils literal notranslate"><span class="pre">L</span></code></td>
<td>进行区域设置感知匹配。</td>
</tr>
<tr class="row-even"><td><code class="xref py py-const docutils literal notranslate"><span class="pre">MULTILINE</span></code>, <code class="xref py py-const docutils literal notranslate"><span class="pre">M</span></code></td>
<td>多行匹配，影响 <code class="docutils literal notranslate"><span class="pre">^</span></code> 和 <code class="docutils literal notranslate"><span class="pre">$</span></code>。</td>
</tr>
<tr class="row-odd"><td><code class="xref py py-const docutils literal notranslate"><span class="pre">VERBOSE</span></code>, <code class="xref py py-const docutils literal notranslate"><span class="pre">X</span></code> （为 '扩展'）</td>
<td>启用详细的正则，可以更清晰，更容易理解。</td>
</tr>
</tbody>
</table>
<dl class="data">
<dt>
<code class="descname">I</code></dt>
<dt>
<code class="descname">IGNORECASE</code></dt>
<dd><p>执行不区分大小写的匹配；字符类和字面字符串将通过忽略大小写来匹配字母。 例如，<code class="docutils literal notranslate"><span class="pre">[A-Z]</span></code> 也匹配小写字母。 除非使用 <code class="xref py py-const docutils literal notranslate"><span class="pre">ASCII</span></code> 标志来禁用非ASCII匹配，否则完全 Unicode 匹配也有效。 当 Unicode 模式 <code class="docutils literal notranslate"><span class="pre">[a-z]</span></code> 或 <code class="docutils literal notranslate"><span class="pre">[A-Z]</span></code> 与 <code class="xref py py-const docutils literal notranslate"><span class="pre">IGNORECASE</span></code> 标志结合使用时，它们将匹配 52 个 ASCII 字母和 4 个额外的非 ASCII 字母：'İ' (U+0130，拉丁大写字母 I，带上面的点)，'ı' (U+0131，拉丁文小写字母无点 i)，'s' (U+017F，拉丁文小写字母长 s) 和'K' (U+212A，开尔文符号)。 <code class="docutils literal notranslate"><span class="pre">Spam</span></code> 将匹配 <code class="docutils literal notranslate"><span class="pre">'Spam'</span></code>，<code class="docutils literal notranslate"><span class="pre">'spam'</span></code>，<code class="docutils literal notranslate"><span class="pre">'spAM'</span></code> 或 <code class="docutils literal notranslate"><span class="pre">'ſpam'</span></code> (后者仅在 Unicode 模式下匹配)。 此小写不考虑当前区域设置；如果你还设置了 <code class="xref py py-const docutils literal notranslate"><span class="pre">LOCALE</span></code> 标志，则将考虑。</p>
</dd></dl>

<dl class="data">
<dt>
<code class="descname">L</code></dt>
<dt>
<code class="descname">LOCALE</code></dt>
<dd><p>使 <code class="docutils literal notranslate"><span class="pre">\w</span></code>、<code class="docutils literal notranslate"><span class="pre">\W</span></code>、<code class="docutils literal notranslate"><span class="pre">\b</span></code>、<code class="docutils literal notranslate"><span class="pre">\B</span></code> 和大小写敏感匹配依赖于当前区域而不是 Unicode 数据库。</p>
<p>区域设置是 C 库的一个功能，旨在帮助编写考虑到语言差异的程序。例如，如果你正在处理编码的法语文本，那么你希望能够编写 <code class="docutils literal notranslate"><span class="pre">\w+</span></code> 来匹配单词，但 <code class="docutils literal notranslate"><span class="pre">\w</span></code> 只匹配字符类 <code class="docutils literal notranslate"><span class="pre">[A-Za-z]</span></code> 字节模式；它不会匹配对应于 <code class="docutils literal notranslate"><span class="pre">é</span></code> 或 <code class="docutils literal notranslate"><span class="pre">ç</span></code> 的字节。如果你的系统配置正确并且选择了法语区域设置，某些C函数将告诉程序对应于 <code class="docutils literal notranslate"><span class="pre">é</span></code> 的字节也应该被视为字母。在编译正则表达式时设置 <code class="xref py py-const docutils literal notranslate"><span class="pre">LOCALE</span></code> 标志将导致生成的编译对象将这些C函数用于 <code class="docutils literal notranslate"><span class="pre">\w</span></code>；这比较慢，但也可以使 <code class="docutils literal notranslate"><span class="pre">\w+</span></code> 匹配你所期望的法语单词。在 Python 3 中不鼓励使用此标志，因为语言环境机制非常不可靠，它一次只处理一个“文化”，它只适用于 8 位语言环境。默认情况下，Python 3 中已经为 Unicode（str）模式启用了 Unicode 匹配，并且它能够处理不同的区域/语言。</p>
</dd></dl>

<dl class="data">
<dt>
<code class="descname">M</code></dt>
<dt>
<code class="descname">MULTILINE</code></dt>
<dd><p>(<code class="docutils literal notranslate"><span class="pre">^</span></code> 和 <code class="docutils literal notranslate"><span class="pre">$</span></code> 还没有解释；它们将在以下部分介绍 <a class="reference internal" href="#more-metacharacters"><span class="std std-ref">更多元字符</span></a>。)</p>
<p>通常 <code class="docutils literal notranslate"><span class="pre">^</span></code> 只匹配字符串的开头，而 <code class="docutils literal notranslate"><span class="pre">$</span></code> 只匹配字符串的结尾，紧接在字符串末尾的换行符（如果有的话）之前。 当指定了这个标志时，<code class="docutils literal notranslate"><span class="pre">^</span></code> 匹配字符串的开头和字符串中每一行的开头，紧跟在每个换行符之后。 类似地，<code class="docutils literal notranslate"><span class="pre">$</span></code> 元字符匹配字符串的结尾和每行的结尾（紧接在每个换行符之前）。</p>
</dd></dl>

<dl class="data">
<dt>
<code class="descname">S</code></dt>
<dt>
<code class="descname">DOTALL</code></dt>
<dd><p>使 <code class="docutils literal notranslate"><span class="pre">'.'</span></code> 特殊字符匹配任何字符，包括换行符；没有这个标志，<code class="docutils literal notranslate"><span class="pre">'.'</span></code> 将匹配任何字符 <em>除了</em> 换行符。</p>
</dd></dl>

<dl class="data">
<dt>
<code class="descname">A</code></dt>
<dt>
<code class="descname">ASCII</code></dt>
<dd><p>使 <code class="docutils literal notranslate"><span class="pre">\w</span></code>、<code class="docutils literal notranslate"><span class="pre">\W</span></code>、<code class="docutils literal notranslate"><span class="pre">\b</span></code>、<code class="docutils literal notranslate"><span class="pre">\B</span></code>、<code class="docutils literal notranslate"><span class="pre">\s</span></code> 和 <code class="docutils literal notranslate"><span class="pre">\S</span></code> 执行仅 ASCII 匹配而不是完整匹配 Unicode 匹配。 这仅对 Unicode 模式有意义，并且对于字节模式将被忽略。</p>
</dd></dl>

<dl class="data">
<dt>
<code class="descname">X</code></dt>
<dt>
<code class="descname">VERBOSE</code></dt>
<dd><p>此标志允许你编写更易读的正则表达式，方法是为您提供更灵活的格式化方式。 指定此标志后，将忽略正则字符串中的空格，除非空格位于字符类中或前面带有未转义的反斜杠；这使你可以更清楚地组织和缩进正则。 此标志还允许你将注释放在正则中，引擎将忽略该注释；注释标记为 <code class="docutils literal notranslate"><span class="pre">'#'</span></code> 既不是在字符类中，也不是在未转义的反斜杠之前。</p>
<p>例如，这里的正则使用 <a class="reference internal" href="../library/re.html#re.VERBOSE" title="re.VERBOSE"><code class="xref py py-const docutils literal notranslate"><span class="pre">re.VERBOSE</span></code></a>；看看阅读有多容易？:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">charref</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> &amp;[#]                # Start of a numeric entity reference</span>
<span class="s2"> (</span>
<span class="s2">     0[0-7]+         # Octal form</span>
<span class="s2">   | [0-9]+          # Decimal form</span>
<span class="s2">   | x[0-9a-fA-F]+   # Hexadecimal form</span>
<span class="s2"> )</span>
<span class="s2"> ;                   # Trailing semicolon</span>
<span class="s2">&quot;&quot;&quot;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span><span class="p">)</span>
</pre></div>
</div>
<p>如果没有详细设置，正则将如下所示:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">charref</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s2">&quot;&amp;#(0[0-7]+&quot;</span>
                     <span class="s2">&quot;|[0-9]+&quot;</span>
                     <span class="s2">&quot;|x[0-9a-fA-F]+);&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>在上面的例子中，Python的字符串文字的自动连接已被用于将正则分解为更小的部分，但它仍然比以下使用 <a class="reference internal" href="../library/re.html#re.VERBOSE" title="re.VERBOSE"><code class="xref py py-const docutils literal notranslate"><span class="pre">re.VERBOSE</span></code></a> 版本更难理解。</p>
</dd></dl>

</div>
</div>
<div class="section" id="more-pattern-power">
<h2>更多模式能力<a class="headerlink" href="#more-pattern-power" title="永久链接至标题">¶</a></h2>
<p>到目前为止，我们只介绍了正则表达式的一部分功能。 在本节中，我们将介绍一些新的元字符，以及如何使用组来检索匹配的文本部分。</p>
<div class="section" id="more-metacharacters">
<span id="id2"></span><h3>更多元字符<a class="headerlink" href="#more-metacharacters" title="永久链接至标题">¶</a></h3>
<p>我们还没有涉及到一些元字符。 其中大部分内容将在本节中介绍。</p>
<p>要讨论的其余一些元字符是 <em class="dfn">零宽度断言</em> 。 它们不会使解析引擎在字符串中前进一个字符；相反，它们根本不占用任何字符，只是成功或失败。例如，<code class="docutils literal notranslate"><span class="pre">\b</span></code> 是一个断言，指明当前位置位于字边界；这个位置根本不会被 <code class="docutils literal notranslate"><span class="pre">\b</span></code> 改变。这意味着永远不应重复零宽度断言，因为如果它们在给定位置匹配一次，它们显然可以无限次匹配。</p>
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">|</span></code></dt>
<dd><p class="first">或者“or”运算符。 如果 <em>A</em> 和 <em>B</em> 是正则表达式，<code class="docutils literal notranslate"><span class="pre">A|B</span></code> 将匹配任何与 <em>A</em> 或 <em>B</em> 匹配的字符串。 <code class="docutils literal notranslate"><span class="pre">|</span></code> 具有非常低的优先级，以便在交替使用多字符字符串时使其合理地工作。 <code class="docutils literal notranslate"><span class="pre">Crow|Servo</span></code> 将匹配 <code class="docutils literal notranslate"><span class="pre">'Crow'</span></code> 或 <code class="docutils literal notranslate"><span class="pre">'Servo'</span></code>，而不是 <code class="docutils literal notranslate"><span class="pre">'Cro'</span></code>、<code class="docutils literal notranslate"><span class="pre">'w'</span></code> 或 <code class="docutils literal notranslate"><span class="pre">'S'</span></code> 和 <code class="docutils literal notranslate"><span class="pre">'ervo'</span></code>。</p>
<p class="last">要匹配字面 <code class="docutils literal notranslate"><span class="pre">'|'</span></code>，请使用 <code class="docutils literal notranslate"><span class="pre">\|</span></code>，或将其括在字符类中，如 <code class="docutils literal notranslate"><span class="pre">[|]</span></code>。</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">^</span></code></dt>
<dd><p class="first">在行的开头匹配。 除非设置了 <code class="xref py py-const docutils literal notranslate"><span class="pre">MULTILINE</span></code> 标志，否则只会在字符串的开头匹配。 在 <code class="xref py py-const docutils literal notranslate"><span class="pre">MULTILINE</span></code> 模式下，这也在字符串中的每个换行符后立即匹配。</p>
<p>例如，如果你希望仅在行的开头匹配单词 <code class="docutils literal notranslate"><span class="pre">From</span></code>，则要使用的正则 <code class="docutils literal notranslate"><span class="pre">^From</span></code>。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;^From&#39;</span><span class="p">,</span> <span class="s1">&#39;From Here to Eternity&#39;</span><span class="p">))</span>  
<span class="go">&lt;re.Match object; span=(0, 4), match=&#39;From&#39;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;^From&#39;</span><span class="p">,</span> <span class="s1">&#39;Reciting From Memory&#39;</span><span class="p">))</span>
<span class="go">None</span>
</pre></div>
</div>
<p class="last">要匹配字面 <code class="docutils literal notranslate"><span class="pre">'^'</span></code>，使用 <code class="docutils literal notranslate"><span class="pre">\^</span></code>。</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">$</span></code></dt>
<dd><p class="first">匹配行的末尾，定义为字符串的结尾，或者后跟换行符的任何位置。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;}$&#39;</span><span class="p">,</span> <span class="s1">&#39;</span><span class="si">{block}</span><span class="s1">&#39;</span><span class="p">))</span>  
<span class="go">&lt;re.Match object; span=(6, 7), match=&#39;}&#39;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;}$&#39;</span><span class="p">,</span> <span class="s1">&#39;</span><span class="si">{block}</span><span class="s1"> &#39;</span><span class="p">))</span>
<span class="go">None</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;}$&#39;</span><span class="p">,</span> <span class="s1">&#39;</span><span class="si">{block}</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">))</span>  
<span class="go">&lt;re.Match object; span=(6, 7), match=&#39;}&#39;&gt;</span>
</pre></div>
</div>
<p class="last">以匹配字面 <code class="docutils literal notranslate"><span class="pre">'$'</span></code>，使用 <code class="docutils literal notranslate"><span class="pre">\$</span></code> 或者将其包裹在一个字符类中，例如 <code class="docutils literal notranslate"><span class="pre">[$]</span></code>。</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\A</span></code></dt>
<dd>仅匹配字符串的开头。 当不在 <code class="xref py py-const docutils literal notranslate"><span class="pre">MULTILINE</span></code> 模式时，<code class="docutils literal notranslate"><span class="pre">\A</span></code> 和 <code class="docutils literal notranslate"><span class="pre">^</span></code> 实际上是相同的。 在 <code class="xref py py-const docutils literal notranslate"><span class="pre">MULTILINE</span></code> 模式中，它们是不同的: <code class="docutils literal notranslate"><span class="pre">\A</span></code> 仍然只在字符串的开头匹配，但 <code class="docutils literal notranslate"><span class="pre">^</span></code> 可以匹配在换行符之后的字符串内的任何位置。</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\Z</span></code></dt>
<dd>只匹配字符串尾。</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\b</span></code></dt>
<dd><p class="first">字边界。 这是一个零宽度断言，仅在单词的开头或结尾处匹配。 单词被定义为一个字母数字字符序列，因此单词的结尾由空格或非字母数字字符表示。</p>
<p>以下示例仅当它是一个完整的单词时匹配 <code class="docutils literal notranslate"><span class="pre">class</span></code>；当它包含在另一个单词中时将不会匹配。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\bclass\b&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;no class at all&#39;</span><span class="p">))</span>
<span class="go">&lt;re.Match object; span=(3, 8), match=&#39;class&#39;&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;the declassified algorithm&#39;</span><span class="p">))</span>
<span class="go">None</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;one subclass is&#39;</span><span class="p">))</span>
<span class="go">None</span>
</pre></div>
</div>
<p>使用这个特殊序列时，你应该记住两个细微之处。 首先，这是 Python 的字符串文字和正则表达式序列之间最严重的冲突。 在 Python 的字符串文字中，<code class="docutils literal notranslate"><span class="pre">\b</span></code> 是退格字符，ASCII 值为8。 如果你没有使用原始字符串，那么 Python 会将 <code class="docutils literal notranslate"><span class="pre">\b</span></code> 转换为退格，你的正则不会按照你的预期匹配。 以下示例与我们之前的正则看起来相同，但省略了正则字符串前面的 <code class="docutils literal notranslate"><span class="pre">'r'</span></code>。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\b</span><span class="s1">class</span><span class="se">\b</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;no class at all&#39;</span><span class="p">))</span>
<span class="go">None</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\b</span><span class="s1">&#39;</span> <span class="o">+</span> <span class="s1">&#39;class&#39;</span> <span class="o">+</span> <span class="s1">&#39;</span><span class="se">\b</span><span class="s1">&#39;</span><span class="p">))</span>
<span class="go">&lt;re.Match object; span=(0, 7), match=&#39;\x08class\x08&#39;&gt;</span>
</pre></div>
</div>
<p class="last">其次，在一个字符类中，这个断言没有用处，<code class="docutils literal notranslate"><span class="pre">\b</span></code> 表示退格字符，以便与 Python 的字符串文字兼容。</p>
</dd>
<dt><code class="docutils literal notranslate"><span class="pre">\B</span></code></dt>
<dd>另一个零宽度断言，这与 <code class="docutils literal notranslate"><span class="pre">\b</span></code> 相反，仅在当前位置不在字边界时才匹配。</dd>
</dl>
</div>
<div class="section" id="grouping">
<h3>分组<a class="headerlink" href="#grouping" title="永久链接至标题">¶</a></h3>
<p>通常，你需要获取更多信息，而不仅仅是正则是否匹配。 正则表达式通常用于通过将正则分成几个子组来解析字符串，这些子组匹配不同的感兴趣组件。 例如，RFC-822 标题行分为标题名称和值，用 <code class="docutils literal notranslate"><span class="pre">':'</span></code> 分隔，如下所示：</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>From: author@example.com
User-Agent: Thunderbird 1.5.0.9 (X11/20061227)
MIME-Version: 1.0
To: editor@example.com
</pre></div>
</div>
<p>这可以通过编写与整个标题行匹配的正则表达式来处理，并且具有与标题名称匹配的一个组，以及与标题的值匹配的另一个组。</p>
<p>组由 <code class="docutils literal notranslate"><span class="pre">'('</span></code>，<code class="docutils literal notranslate"><span class="pre">')'`</span></code> 元字符标记。 <code class="docutils literal notranslate"><span class="pre">'('</span></code> 和 <code class="docutils literal notranslate"><span class="pre">')'</span></code> 与数学表达式的含义大致相同；它们将包含在其中的表达式组合在一起，你可以使用重复限定符重复组的内容，例如 <code class="docutils literal notranslate"><span class="pre">*</span></code>，<code class="docutils literal notranslate"><span class="pre">+</span></code>，<code class="docutils literal notranslate"><span class="pre">?</span></code> 或 <code class="docutils literal notranslate"><span class="pre">{m,n}</span></code>。 例如，<code class="docutils literal notranslate"><span class="pre">(ab)*</span></code> 将匹配 <code class="docutils literal notranslate"><span class="pre">ab</span></code> 的零次或多次重复。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;(ab)*&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;ababababab&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">span</span><span class="p">())</span>
<span class="go">(0, 10)</span>
</pre></div>
</div>
<p>用 <code class="docutils literal notranslate"><span class="pre">'('</span></code>，<code class="docutils literal notranslate"><span class="pre">')'</span></code> 表示的组也捕获它们匹配的文本的起始和结束索引；这可以通过将参数传递给 <a class="reference internal" href="../library/re.html#re.Match.group" title="re.Match.group"><code class="xref py py-meth docutils literal notranslate"><span class="pre">group()</span></code></a>、<a class="reference internal" href="../library/re.html#re.Match.start" title="re.Match.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a>、<a class="reference internal" href="../library/re.html#re.Match.end" title="re.Match.end"><code class="xref py py-meth docutils literal notranslate"><span class="pre">end()</span></code></a> 以及 <a class="reference internal" href="../library/re.html#re.Match.span" title="re.Match.span"><code class="xref py py-meth docutils literal notranslate"><span class="pre">span()</span></code></a>。 组从 0 开始编号。组 0 始终存在；它表示整个正则，所以 <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a> 方法都将组 0 作为默认参数。 稍后我们将看到如何表达不捕获它们匹配的文本范围的组。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;(a)b&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;ab&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
<span class="go">&#39;ab&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="go">&#39;ab&#39;</span>
</pre></div>
</div>
<p>子组从左到右编号，从 1 向上编号。 组可以嵌套；要确定编号，只需计算从左到右的左括号字符。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;(a(b)c)d&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;abcd&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="go">&#39;abcd&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">&#39;abc&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="go">&#39;b&#39;</span>
</pre></div>
</div>
<p><a class="reference internal" href="../library/re.html#re.Match.group" title="re.Match.group"><code class="xref py py-meth docutils literal notranslate"><span class="pre">group()</span></code></a> 可以一次传递多个组号，在这种情况下，它将返回一个包含这些组的相应值的元组。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span>
<span class="go">(&#39;b&#39;, &#39;abc&#39;, &#39;b&#39;)</span>
</pre></div>
</div>
<p><a class="reference internal" href="../library/re.html#re.Match.groups" title="re.Match.groups"><code class="xref py py-meth docutils literal notranslate"><span class="pre">groups()</span></code></a> 方法返回一个元组，其中包含所有子组的字符串，从1到最后一个子组。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">groups</span><span class="p">()</span>
<span class="go">(&#39;abc&#39;, &#39;b&#39;)</span>
</pre></div>
</div>
<p>模式中的后向引用允许你指定还必须在字符串中的当前位置找到先前捕获组的内容。 例如，如果可以在当前位置找到组 1 的确切内容，则 <code class="docutils literal notranslate"><span class="pre">\1</span></code> 将成功，否则将失败。 请记住，Python 的字符串文字也使用反斜杠后跟数字以允许在字符串中包含任意字符，因此正则中引入反向引用时务必使用原始字符串。</p>
<p>例如，以下正则检测字符串中的双字。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\b(\w+)\s+\1\b&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;Paris in the the spring&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
<span class="go">&#39;the the&#39;</span>
</pre></div>
</div>
<p>像这样的后向引用通常不仅仅用于搜索字符串 —— 很少有文本格式以这种方式重复数据 —— 但是你很快就会发现它们在执行字符串替换时 <em>非常</em> 有用。</p>
</div>
<div class="section" id="non-capturing-and-named-groups">
<h3>非捕获和命名组<a class="headerlink" href="#non-capturing-and-named-groups" title="永久链接至标题">¶</a></h3>
<p>精心设计的正则可以使用许多组，既可以捕获感兴趣的子串，也可以对正则本身进行分组和构建。 在复杂的正则中，很难跟踪组号。 有两个功能可以帮助解决这个问题。 它们都使用常用语法进行正则表达式扩展，因此我们首先看一下。</p>
<p>Perl 5 以其对标准正则表达式的强大补充而闻名。 对于这些新功能，Perl 开发人员无法选择新的单键击元字符或以 <code class="docutils literal notranslate"><span class="pre">\</span></code> 开头的新特殊序列，否则 Perl 的正则表达式与标准正则容易混淆。 例如，如果他们选择 <code class="docutils literal notranslate"><span class="pre">&amp;</span></code> 作为一个新的元字符，旧的表达式将假设 <code class="docutils literal notranslate"><span class="pre">&amp;</span></code> 是一个普通字符，并且不会编写 <code class="docutils literal notranslate"><span class="pre">\&amp;</span></code> 或 <code class="docutils literal notranslate"><span class="pre">[&amp;]</span></code>。</p>
<p>Perl 开发人员选择的解决方案是使用 <code class="docutils literal notranslate"><span class="pre">(?...)</span></code> 作为扩展语法。 括号后面的 <code class="docutils literal notranslate"><span class="pre">?</span></code> 是一个语法错误，因为 <code class="docutils literal notranslate"><span class="pre">?</span></code> 没有什么可重复的，所以这并没有引入任何兼容性问题。 紧跟在 <code class="docutils literal notranslate"><span class="pre">?</span></code> 之后的字符表示正在使用什么扩展名，所以 <code class="docutils literal notranslate"><span class="pre">(?=foo)</span></code> 是一个东西（一个正向的先行断言）和 <code class="docutils literal notranslate"><span class="pre">(?:foo)</span></code> 是其它东西（ 包含子表达式 <code class="docutils literal notranslate"><span class="pre">foo</span></code> 的非捕获组）。</p>
<p>Python 支持一些 Perl 的扩展，并增加了新的扩展语法用于 Perl 的扩展语法。 如果在问号之后的第一个字符为 <code class="docutils literal notranslate"><span class="pre">P</span></code>，即表明其为 Python 专属的扩展。</p>
<p>现在我们已经了解了一般的扩展语法，我们可以回到简化复杂正则中组处理的功能。</p>
<p>有时你会想要使用组来表示正则表达式的一部分，但是对检索组的内容不感兴趣。 你可以通过使用非捕获组来显式表达这个事实: <code class="docutils literal notranslate"><span class="pre">(?:...)</span></code>，你可以用任何其他正则表达式替换 <code class="docutils literal notranslate"><span class="pre">...</span></code>。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s2">&quot;([abc])+&quot;</span><span class="p">,</span> <span class="s2">&quot;abc&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">groups</span><span class="p">()</span>
<span class="go">(&#39;c&#39;,)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s2">&quot;(?:[abc])+&quot;</span><span class="p">,</span> <span class="s2">&quot;abc&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">groups</span><span class="p">()</span>
<span class="go">()</span>
</pre></div>
</div>
<p>除了你无法检索组匹配内容的事实外，非捕获组的行为与捕获组完全相同；你可以在里面放任何东西，用重复元字符重复它，比如 <code class="docutils literal notranslate"><span class="pre">*</span></code>，然后把它嵌入其他组（捕获或不捕获）。 <code class="docutils literal notranslate"><span class="pre">(?:...)</span></code> 在修改现有模式时特别有用，因为你可以添加新组而不更改所有其他组的编号方式。 值得一提的是，捕获和非捕获组之间的搜索没有性能差异；两种形式没有一种更快。</p>
<p>更重要的功能是命名组：不是通过数字引用它们，而是可以通过名称引用组。</p>
<p>命名组的语法是Python特定的扩展之一: <code class="docutils literal notranslate"><span class="pre">(?P&lt;name&gt;...)</span></code>。 <em>name</em> 显然是该组的名称。 命名组的行为与捕获组完全相同，并且还将名称与组关联。 处理捕获组的 <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a> 方法都接受按编号引用组的整数或包含所需组名的字符串。 命名组仍然是给定的数字，因此你可以通过两种方式检索有关组的信息:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;(?P&lt;word&gt;\b\w+\b)&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span> <span class="s1">&#39;(((( Lots of punctuation )))&#39;</span> <span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s1">&#39;word&#39;</span><span class="p">)</span>
<span class="go">&#39;Lots&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">&#39;Lots&#39;</span>
</pre></div>
</div>
<p>命名组很有用，因为它们允许你使用容易记住的名称，而不必记住数字。 这是来自 <a class="reference internal" href="../library/imaplib.html#module-imaplib" title="imaplib: IMAP4 protocol client (requires sockets)."><code class="xref py py-mod docutils literal notranslate"><span class="pre">imaplib</span></code></a> 模块的示例正则</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">InternalDate</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;INTERNALDATE &quot;&#39;</span>
        <span class="sa">r</span><span class="s1">&#39;(?P&lt;day&gt;[ 123][0-9])-(?P&lt;mon&gt;[A-Z][a-z][a-z])-&#39;</span>
        <span class="sa">r</span><span class="s1">&#39;(?P&lt;year&gt;[0-9][0-9][0-9][0-9])&#39;</span>
        <span class="sa">r</span><span class="s1">&#39; (?P&lt;hour&gt;[0-9][0-9]):(?P&lt;min&gt;[0-9][0-9]):(?P&lt;sec&gt;[0-9][0-9])&#39;</span>
        <span class="sa">r</span><span class="s1">&#39; (?P&lt;zonen&gt;[-+])(?P&lt;zoneh&gt;[0-9][0-9])(?P&lt;zonem&gt;[0-9][0-9])&#39;</span>
        <span class="sa">r</span><span class="s1">&#39;&quot;&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>检索 <code class="docutils literal notranslate"><span class="pre">m.group('zonem')</span></code> 显然要容易得多，而不必记住检索第 9 组。</p>
<p>表达式中的后向引用语法，例如 <code class="docutils literal notranslate"><span class="pre">(...)\1</span></code>，指的是组的编号。 当然有一种变体使用组名而不是数字。 这是另一个 Python 扩展: <code class="docutils literal notranslate"><span class="pre">(?P=name)</span></code> 表示在当前点再次匹配名为 <em>name</em> 的组的内容。 用于查找双字的正则表达式，<code class="docutils literal notranslate"><span class="pre">\b(\w+)\s+\1\b</span></code> 也可以写为 <code class="docutils literal notranslate"><span class="pre">\b(?P&lt;word&gt;\w+)\s+(?P=word)\b</span></code>:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\b(?P&lt;word&gt;\w+)\s+(?P=word)\b&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;Paris in the the spring&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
<span class="go">&#39;the the&#39;</span>
</pre></div>
</div>
</div>
<div class="section" id="lookahead-assertions">
<h3>前向断言<a class="headerlink" href="#lookahead-assertions" title="永久链接至标题">¶</a></h3>
<p>另一个零宽度断言是前向断言。 前向断言以正面和负面形式提供，如下所示：</p>
<dl class="docutils">
<dt><code class="docutils literal notranslate"><span class="pre">(?=…)</span></code></dt>
<dd>正向前向断言。 如果包含的正则表达式，由 <code class="docutils literal notranslate"><span class="pre">...</span></code> 表示，在当前位置成功匹配，则成功，否则失败。 但是，一旦尝试了包含的表达式，匹配的引擎就不会前进；模式其余的部分会在在断言开始的地方尝试。</dd>
<dt><code class="docutils literal notranslate"><span class="pre">(?!…)</span></code></dt>
<dd>负向前向断言。 这与积正向断言相反；如果包含的表达式在字符串中的当前位置 <em>不</em> 匹配，则成功。</dd>
</dl>
<p>更具体一些，让我们看看前向是有用的情况。 考虑一个简单的模式来匹配文件名并将其拆分为基本名称和扩展名，用 <code class="docutils literal notranslate"><span class="pre">.</span></code> 分隔。 例如，在 <code class="docutils literal notranslate"><span class="pre">news.rc</span></code> 中，<code class="docutils literal notranslate"><span class="pre">news</span></code> 是基本名称，<code class="docutils literal notranslate"><span class="pre">rc</span></code> 是文件名的扩展名。</p>
<p>与此匹配的模式非常简单：</p>
<p><code class="docutils literal notranslate"><span class="pre">.*[.].*$</span></code></p>
<p>请注意，<code class="docutils literal notranslate"><span class="pre">.</span></code> 需要特别处理，因为它是元字符，所以它在字符类中只能匹配特定字符。 还要注意尾随的 <code class="docutils literal notranslate"><span class="pre">$</span></code>；添加此项以确保扩展名中的所有其余字符串都必须包含在扩展名中。 这个正则表达式匹配 <code class="docutils literal notranslate"><span class="pre">foo.bar</span></code>、<code class="docutils literal notranslate"><span class="pre">autoexec.bat</span></code>、<code class="docutils literal notranslate"><span class="pre">sendmail.cf</span></code> 和 <code class="docutils literal notranslate"><span class="pre">printers.conf</span></code>。</p>
<p>现在，考虑使更复杂一点的问题；如果你想匹配扩展名不是 <code class="docutils literal notranslate"><span class="pre">bat</span></code> 的文件名怎么办？ 一些错误的尝试：</p>
<p><code class="docutils literal notranslate"><span class="pre">.*[.][^b].*$</span></code> 上面的第一次尝试试图通过要求扩展名的第一个字符不是 <code class="docutils literal notranslate"><span class="pre">b</span></code> 来排除 <code class="docutils literal notranslate"><span class="pre">bat</span></code>。 这是错误的，因为模式也与 <code class="docutils literal notranslate"><span class="pre">foo.bar</span></code> 不匹配。</p>
<p><code class="docutils literal notranslate"><span class="pre">.*[.]([^b]..|.[^a].|..[^t])$</span></code></p>
<p>当你尝试通过要求以下一种情况匹配来修补第一个解决方案时，表达式变得更加混乱：扩展的第一个字符不是 <code class="docutils literal notranslate"><span class="pre">b</span></code>。 第二个字符不 <code class="docutils literal notranslate"><span class="pre">a</span></code>；或者第三个字符不是 <code class="docutils literal notranslate"><span class="pre">t</span></code>。 这接受 <code class="docutils literal notranslate"><span class="pre">foo.bar</span></code> 并拒绝 <code class="docutils literal notranslate"><span class="pre">autoexec.bat</span></code>，但它需要三个字母的扩展名，并且不接受带有两个字母扩展名的文件名，例如 <code class="docutils literal notranslate"><span class="pre">sendmail.cf</span></code>。 为了解决这个问题，我们会再次使模式复杂化。</p>
<p><code class="docutils literal notranslate"><span class="pre">.*[.]([^b].?.?|.[^a]?.?|..?[^t]?)$</span></code></p>
<p>在第三次尝试中，第二个和第三个字母都是可选的，以便允许匹配的扩展名短于三个字符，例如 <code class="docutils literal notranslate"><span class="pre">sendmail.cf</span></code>。</p>
<p>模式现在变得非常复杂，这使得它难以阅读和理解。 更糟糕的是，如果问题发生变化并且你想要将 <code class="docutils literal notranslate"><span class="pre">bat</span></code> 和 <code class="docutils literal notranslate"><span class="pre">exe</span></code> 排除为扩展，那么该模式将变得更加复杂和混乱。</p>
<p>负面前向消除了所有这些困扰：</p>
<p><code class="docutils literal notranslate"><span class="pre">.*[.](?!bat$)[^.]*$</span></code> 负向前向意味着：如果表达式 <code class="docutils literal notranslate"><span class="pre">bat</span></code> 此时不匹配，请尝试其余的模式；如果 <code class="docutils literal notranslate"><span class="pre">bat$</span></code> 匹配，整个模式将失败。 尾随的 <code class="docutils literal notranslate"><span class="pre">$</span></code> 是必需的，以确保允许像 <code class="docutils literal notranslate"><span class="pre">sample.batch</span></code> 这样的扩展只以 <code class="docutils literal notranslate"><span class="pre">bat</span></code> 开头的文件能通过。 <code class="docutils literal notranslate"><span class="pre">[^.]*</span></code> 确保当文件名中有多个点时，模式有效。</p>
<p>现在很容易排除另一个文件扩展名；只需在断言中添加它作为替代。  以下模块排除以 <code class="docutils literal notranslate"><span class="pre">bat</span></code> 或 <code class="docutils literal notranslate"><span class="pre">exe</span></code>:</p>
<p><code class="docutils literal notranslate"><span class="pre">.*[.](?!bat$|exe$)[^.]*$</span></code></p>
</div>
</div>
<div class="section" id="modifying-strings">
<h2>修改字符串<a class="headerlink" href="#modifying-strings" title="永久链接至标题">¶</a></h2>
<p>到目前为止，我们只是针对静态字符串执行搜索。 正则表达式通常也用于以各种方式修改字符串，使用以下模式方法：</p>
<table border="1" class="docutils">
<colgroup>
<col width="28%" />
<col width="72%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">方法 / 属性</th>
<th class="head">目的</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">split()</span></code></td>
<td>将字符串拆分为一个列表，在正则匹配的任何地方将其拆分</td>
</tr>
<tr class="row-odd"><td><code class="docutils literal notranslate"><span class="pre">sub()</span></code></td>
<td>找到正则匹配的所有子字符串，并用不同的字符串替换它们</td>
</tr>
<tr class="row-even"><td><code class="docutils literal notranslate"><span class="pre">subn()</span></code></td>
<td>与 <code class="xref py py-meth docutils literal notranslate"><span class="pre">sub()</span></code> 相同，但返回新字符串和替换次数</td>
</tr>
</tbody>
</table>
<div class="section" id="splitting-strings">
<h3>分割字符串<a class="headerlink" href="#splitting-strings" title="永久链接至标题">¶</a></h3>
<p>模式的 <a class="reference internal" href="../library/re.html#re.Pattern.split" title="re.Pattern.split"><code class="xref py py-meth docutils literal notranslate"><span class="pre">split()</span></code></a> 方法在正则匹配的任何地方拆分字符串，返回一个片段列表。 它类似于 <a class="reference internal" href="../library/stdtypes.html#str.split" title="str.split"><code class="xref py py-meth docutils literal notranslate"><span class="pre">split()</span></code></a> 字符串方法，但在分隔符的分隔符中提供了更多的通用性；字符串的 <code class="xref py py-meth docutils literal notranslate"><span class="pre">split()</span></code> 仅支持按空格或固定字符串进行拆分。 正如你所期望的那样，还有一个模块级 <a class="reference internal" href="../library/re.html#re.split" title="re.split"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.split()</span></code></a> 函数。</p>
<dl class="method">
<dt>
<code class="descclassname">.</code><code class="descname">split</code><span class="sig-paren">(</span><em>string</em><span class="optional">[</span>, <em>maxsplit=0</em><span class="optional">]</span><span class="sig-paren">)</span></dt>
<dd><p>通过正则表达式的匹配拆分 <em>字符串</em>。 如果在正则中使用捕获括号，则它们的内容也将作为结果列表的一部分返回。 如果 <em>maxsplit</em> 非零，则最多执行 <em>maxsplit</em> 次拆分。</p>
</dd></dl>

<p>你可以通过传递 <em>maxsplit</em> 的值来限制分割的数量。 当 <em>maxsplit</em> 非零时，将最多进行 <em>maxsplit</em> 次拆分，并且字符串的其余部分将作为列表的最后一个元素返回。 在以下示例中，分隔符是任何非字母数字字符序列。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\W+&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;This is a test, short and sweet, of split().&#39;</span><span class="p">)</span>
<span class="go">[&#39;This&#39;, &#39;is&#39;, &#39;a&#39;, &#39;test&#39;, &#39;short&#39;, &#39;and&#39;, &#39;sweet&#39;, &#39;of&#39;, &#39;split&#39;, &#39;&#39;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;This is a test, short and sweet, of split().&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="go">[&#39;This&#39;, &#39;is&#39;, &#39;a&#39;, &#39;test, short and sweet, of split().&#39;]</span>
</pre></div>
</div>
<p>有时你不仅对分隔符之间的文本感兴趣，而且还需要知道分隔符是什么。 如果在正则中使用捕获括号，则它们的值也将作为列表的一部分返回。 比较以下调用:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\W+&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p2</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;(\W+)&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;This... is a test.&#39;</span><span class="p">)</span>
<span class="go">[&#39;This&#39;, &#39;is&#39;, &#39;a&#39;, &#39;test&#39;, &#39;&#39;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p2</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;This... is a test.&#39;</span><span class="p">)</span>
<span class="go">[&#39;This&#39;, &#39;... &#39;, &#39;is&#39;, &#39; &#39;, &#39;a&#39;, &#39; &#39;, &#39;test&#39;, &#39;.&#39;, &#39;&#39;]</span>
</pre></div>
</div>
<p>模块级函数 <a class="reference internal" href="../library/re.html#re.split" title="re.split"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.split()</span></code></a> 添加要正则作为第一个参数，但在其他方面是相同的。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;[\W]+&#39;</span><span class="p">,</span> <span class="s1">&#39;Words, words, words.&#39;</span><span class="p">)</span>
<span class="go">[&#39;Words&#39;, &#39;words&#39;, &#39;words&#39;, &#39;&#39;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;([\W]+)&#39;</span><span class="p">,</span> <span class="s1">&#39;Words, words, words.&#39;</span><span class="p">)</span>
<span class="go">[&#39;Words&#39;, &#39;, &#39;, &#39;words&#39;, &#39;, &#39;, &#39;words&#39;, &#39;.&#39;, &#39;&#39;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;[\W]+&#39;</span><span class="p">,</span> <span class="s1">&#39;Words, words, words.&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="go">[&#39;Words&#39;, &#39;words, words.&#39;]</span>
</pre></div>
</div>
</div>
<div class="section" id="search-and-replace">
<h3>搜索和替换<a class="headerlink" href="#search-and-replace" title="永久链接至标题">¶</a></h3>
<p>另一个常见任务是找到模式的所有匹配项，并用不同的字符串替换它们。 <a class="reference internal" href="../library/re.html#re.Pattern.sub" title="re.Pattern.sub"><code class="xref py py-meth docutils literal notranslate"><span class="pre">sub()</span></code></a> 方法接受一个替换值，可以是字符串或函数，也可以是要处理的字符串。</p>
<dl class="method">
<dt>
<code class="descclassname">.</code><code class="descname">sub</code><span class="sig-paren">(</span><em>replacement</em>, <em>string</em><span class="optional">[</span>, <em>count=0</em><span class="optional">]</span><span class="sig-paren">)</span></dt>
<dd><p>返回通过替换 <em>replacement</em> 替换 <em>string</em> 中正则的最左边非重叠出现而获得的字符串。 如果未找到模式，则 <em>string</em> 将保持不变。</p>
<p>可选参数 <em>count</em> 是要替换的模式最大的出现次数；<em>count</em> 必须是非负整数。 默认值 0 表示替换所有。</p>
</dd></dl>

<p>这是一个使用 <a class="reference internal" href="../library/re.html#re.Pattern.sub" title="re.Pattern.sub"><code class="xref py py-meth docutils literal notranslate"><span class="pre">sub()</span></code></a> 方法的简单示例。 它用 <code class="docutils literal notranslate"><span class="pre">colour</span></code> 这个词取代颜色名称:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;(blue|white|red)&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s1">&#39;colour&#39;</span><span class="p">,</span> <span class="s1">&#39;blue socks and red shoes&#39;</span><span class="p">)</span>
<span class="go">&#39;colour socks and colour shoes&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s1">&#39;colour&#39;</span><span class="p">,</span> <span class="s1">&#39;blue socks and red shoes&#39;</span><span class="p">,</span> <span class="n">count</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="go">&#39;colour socks and red shoes&#39;</span>
</pre></div>
</div>
<p><a class="reference internal" href="../library/re.html#re.Pattern.subn" title="re.Pattern.subn"><code class="xref py py-meth docutils literal notranslate"><span class="pre">subn()</span></code></a> 方法完成相同的工作，但返回一个包含新字符串值和已执行的替换次数的 2 元组:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;(blue|white|red)&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">subn</span><span class="p">(</span><span class="s1">&#39;colour&#39;</span><span class="p">,</span> <span class="s1">&#39;blue socks and red shoes&#39;</span><span class="p">)</span>
<span class="go">(&#39;colour socks and colour shoes&#39;, 2)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">subn</span><span class="p">(</span><span class="s1">&#39;colour&#39;</span><span class="p">,</span> <span class="s1">&#39;no colours at all&#39;</span><span class="p">)</span>
<span class="go">(&#39;no colours at all&#39;, 0)</span>
</pre></div>
</div>
<p>仅当空匹配与前一个空匹配不相邻时，才会替换空匹配。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;x*&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s1">&#39;-&#39;</span><span class="p">,</span> <span class="s1">&#39;abxd&#39;</span><span class="p">)</span>
<span class="go">&#39;-a-b--d-&#39;</span>
</pre></div>
</div>
<p>如果 <em>replacement</em> 是一个字符串，则处理其中的任何反斜杠转义。 也就是说，<code class="docutils literal notranslate"><span class="pre">\n</span></code> 被转换为单个换行符，<code class="docutils literal notranslate"><span class="pre">\r</span></code> 被转换为回车符，依此类推。 诸如 <code class="docutils literal notranslate"><span class="pre">\&amp;</span></code> 之类的未知转义是孤立的。 后向引用，例如 <code class="docutils literal notranslate"><span class="pre">\6</span></code>，被替换为正则中相应组匹配的子字符串。 这使你可以在生成的替换字符串中合并原始文本的部分内容。</p>
<p>这个例子匹配单词 <code class="docutils literal notranslate"><span class="pre">section</span></code> 后跟一个用 <code class="docutils literal notranslate"><span class="pre">{</span></code>，<code class="docutils literal notranslate"><span class="pre">}</span></code> 括起来的字符串，并将 <code class="docutils literal notranslate"><span class="pre">section</span></code> 改为 <code class="docutils literal notranslate"><span class="pre">subsection</span></code></p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;section{ ( [^}]* ) }&#39;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;subsection{\1}&#39;</span><span class="p">,</span><span class="s1">&#39;section</span><span class="si">{First}</span><span class="s1"> section</span><span class="si">{second}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="go">&#39;subsection{First} subsection{second}&#39;</span>
</pre></div>
</div>
<p>还有一种语法用于引用由 <code class="docutils literal notranslate"><span class="pre">(?P&lt;name&gt;...)</span></code> 语法定义的命名组。 <code class="docutils literal notranslate"><span class="pre">\g&lt;name&gt;</span></code> 将使用名为 <code class="docutils literal notranslate"><span class="pre">name</span></code> 的组匹配的子字符串，<code class="docutils literal notranslate"><span class="pre">\g&lt;number&gt;</span></code> 使用相应的组号。 因此 <code class="docutils literal notranslate"><span class="pre">\g&lt;2&gt;</span></code> 等同于 <code class="docutils literal notranslate"><span class="pre">\2</span></code>，但在诸如 <code class="docutils literal notranslate"><span class="pre">\g&lt;2&gt;0</span></code> 之类的替换字符串中并不模糊。 (<code class="docutils literal notranslate"><span class="pre">\20</span></code> 将被解释为对组 20 的引用，而不是对组 2 的引用，后跟字面字符 <code class="docutils literal notranslate"><span class="pre">'0'</span></code>。) 以下替换都是等效的，但使用所有三种变体替换字符串。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s1">&#39;section{ (?P&lt;name&gt; [^}]* ) }&#39;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;subsection{\1}&#39;</span><span class="p">,</span><span class="s1">&#39;section</span><span class="si">{First}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="go">&#39;subsection{First}&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;subsection{\g&lt;1&gt;}&#39;</span><span class="p">,</span><span class="s1">&#39;section</span><span class="si">{First}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="go">&#39;subsection{First}&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;subsection{\g&lt;name&gt;}&#39;</span><span class="p">,</span><span class="s1">&#39;section</span><span class="si">{First}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="go">&#39;subsection{First}&#39;</span>
</pre></div>
</div>
<p><em>replacement</em> 也可以是一个函数，它可以为你提供更多控制。 如果 <em>replacement</em> 是一个函数，则为 <em>pattern</em> 的每次非重叠出现将调用该函数。 在每次调用时，函数都会传递一个匹配的 <a class="reference internal" href="../library/re.html#match-objects"><span class="std std-ref">匹配对象</span></a> 参数，并可以使用此信息计算所需的替换字符串并将其返回。</p>
<p>在以下示例中，替换函数将小数转换为十六进制:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">hexrepl</span><span class="p">(</span><span class="n">match</span><span class="p">):</span>
<span class="gp">... </span>    <span class="s2">&quot;Return the hex string for a decimal number&quot;</span>
<span class="gp">... </span>    <span class="n">value</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">())</span>
<span class="gp">... </span>    <span class="k">return</span> <span class="nb">hex</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\d+&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="n">hexrepl</span><span class="p">,</span> <span class="s1">&#39;Call 65490 for printing, 49152 for user code.&#39;</span><span class="p">)</span>
<span class="go">&#39;Call 0xffd2 for printing, 0xc000 for user code.&#39;</span>
</pre></div>
</div>
<p>使用模块级别 <a class="reference internal" href="../library/re.html#re.sub" title="re.sub"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.sub()</span></code></a> 函数时，模式作为第一个参数传递。 图案可以作为对象或字符串提供；如果需要指定正则表达式标志，则必须使用模式对象作为第一个参数，或者在模式字符串中使用嵌入式修饰符，例如: <code class="docutils literal notranslate"><span class="pre">sub(&quot;(?i)b+&quot;,</span> <span class="pre">&quot;x&quot;,</span> <span class="pre">&quot;bbbb</span> <span class="pre">BBBB&quot;)</span></code> 返回 <code class="docutils literal notranslate"><span class="pre">'x</span> <span class="pre">x'</span></code>。</p>
</div>
</div>
<div class="section" id="common-problems">
<h2>常见问题<a class="headerlink" href="#common-problems" title="永久链接至标题">¶</a></h2>
<p>正则表达式对于某些应用程序来说是一个强大的工具，但在某些方面，它们的行为并不直观，有时它们的行为方式与你的预期不同。 本节将指出一些最常见的陷阱。</p>
<div class="section" id="use-string-methods">
<h3>使用字符串方法<a class="headerlink" href="#use-string-methods" title="永久链接至标题">¶</a></h3>
<p>有时使用 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块是一个错误。 如果你匹配固定字符串或单个字符类，并且你没有使用任何 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 功能，例如 <a class="reference internal" href="../library/re.html#re.IGNORECASE" title="re.IGNORECASE"><code class="xref py py-const docutils literal notranslate"><span class="pre">IGNORECASE</span></code></a> 标志，那么正则表达式的全部功能可能不是必需的。 字符串有几种方法可以使用固定字符串执行操作，它们通常要快得多，因为实现是一个针对此目的而优化的单个小 C 循环，而不是大型、更通用的正则表达式引擎。</p>
<p>一个例子可能是用另一个固定字符串替换一个固定字符串；例如，你可以用 <code class="docutils literal notranslate"><span class="pre">deed</span></code> 替换 <code class="docutils literal notranslate"><span class="pre">word</span></code> 。 <a class="reference internal" href="../library/re.html#re.sub" title="re.sub"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.sub()</span></code></a> 看起来像是用于此的函数，但请考虑 <a class="reference internal" href="../library/stdtypes.html#str.replace" title="str.replace"><code class="xref py py-meth docutils literal notranslate"><span class="pre">replace()</span></code></a> 方法。 注意 <code class="xref py py-meth docutils literal notranslate"><span class="pre">replace()</span></code> 也会替换单词里面的 <code class="docutils literal notranslate"><span class="pre">word</span></code> ，把 <code class="docutils literal notranslate"><span class="pre">swordfish</span></code> 变成 <code class="docutils literal notranslate"><span class="pre">sdeedfish</span></code> ，但简单的正则 <code class="docutils literal notranslate"><span class="pre">word</span></code> 也会这样做。 （为了避免对单词的部分进行替换，模式必须是 <code class="docutils literal notranslate"><span class="pre">\bword\b</span></code>，以便要求 <code class="docutils literal notranslate"><span class="pre">word</span></code> 在任何一方都有一个单词边界。这使得工作超出了 <code class="xref py py-meth docutils literal notranslate"><span class="pre">replace()</span></code> 的能力。）</p>
<p>另一个常见任务是从字符串中删除单个字符的每个匹配项或将其替换为另一个字符。 你可以用 <code class="docutils literal notranslate"><span class="pre">re.sub('\n',</span> <span class="pre">'</span> <span class="pre">',</span> <span class="pre">S)</span></code> 之类的东西来做这件事，但是 <a class="reference internal" href="../library/stdtypes.html#str.translate" title="str.translate"><code class="xref py py-meth docutils literal notranslate"><span class="pre">translate()</span></code></a> 能够完成这两项任务，并且比任何正则表达式都快。</p>
<p>简而言之，在转向 <a class="reference internal" href="../library/re.html#module-re" title="re: Regular expression operations."><code class="xref py py-mod docutils literal notranslate"><span class="pre">re</span></code></a> 模块之前，请考虑是否可以使用更快更简单的字符串方法解决问题。</p>
</div>
<div class="section" id="match-versus-search">
<h3>match() 和 search()<a class="headerlink" href="#match-versus-search" title="永久链接至标题">¶</a></h3>
<p>The <a class="reference internal" href="../library/re.html#re.match" title="re.match"><code class="xref py py-func docutils literal notranslate"><span class="pre">match()</span></code></a> function only checks if the RE matches at the beginning of the
string while <a class="reference internal" href="../library/re.html#re.search" title="re.search"><code class="xref py py-func docutils literal notranslate"><span class="pre">search()</span></code></a> will scan forward through the string for a match.
It's important to keep this distinction in mind.  Remember,  <code class="xref py py-func docutils literal notranslate"><span class="pre">match()</span></code> will
only report a successful match which will start at 0; if the match wouldn't
start at zero,  <code class="xref py py-func docutils literal notranslate"><span class="pre">match()</span></code> will <em>not</em> report it.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;super&#39;</span><span class="p">,</span> <span class="s1">&#39;superstition&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">span</span><span class="p">())</span>
<span class="go">(0, 5)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;super&#39;</span><span class="p">,</span> <span class="s1">&#39;insuperable&#39;</span><span class="p">))</span>
<span class="go">None</span>
</pre></div>
</div>
<p>另一方面， <a class="reference internal" href="../library/re.html#re.search" title="re.search"><code class="xref py py-func docutils literal notranslate"><span class="pre">search()</span></code></a> 将向前扫描字符串，报告它找到的第一个匹配项。:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;super&#39;</span><span class="p">,</span> <span class="s1">&#39;superstition&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">span</span><span class="p">())</span>
<span class="go">(0, 5)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="s1">&#39;super&#39;</span><span class="p">,</span> <span class="s1">&#39;insuperable&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">span</span><span class="p">())</span>
<span class="go">(2, 7)</span>
</pre></div>
</div>
<p>有时你会被诱惑继续使用 <a class="reference internal" href="../library/re.html#re.match" title="re.match"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.match()</span></code></a> ，只需在你的正则前面添加 <code class="docutils literal notranslate"><span class="pre">.*</span></code> 。抵制这种诱惑并使用 <a class="reference internal" href="../library/re.html#re.search" title="re.search"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.search()</span></code></a> 代替。 正则表达式编译器对正则进行一些分析，以加快寻找匹配的过程。 其中一个分析可以确定匹配的第一个特征必须是什么；例如，以 <code class="docutils literal notranslate"><span class="pre">Crow</span></code> 开头的模式必须与 <code class="docutils literal notranslate"><span class="pre">'C'</span></code> 匹配。 分析让引擎快速扫描字符串，寻找起始字符，只在找到 <code class="docutils literal notranslate"><span class="pre">'C'</span></code> 时尝试完全匹配。</p>
<p>添加 <code class="docutils literal notranslate"><span class="pre">.*</span></code> 会使这个优化失效，需要扫描到字符串的末尾，然后回溯以找到正则的其余部分的匹配。 使用 <a class="reference internal" href="../library/re.html#re.search" title="re.search"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.search()</span></code></a> 代替。</p>
</div>
<div class="section" id="greedy-versus-non-greedy">
<h3>贪婪与非贪婪<a class="headerlink" href="#greedy-versus-non-greedy" title="永久链接至标题">¶</a></h3>
<p>当重复一个正则表达式时，就像在 <code class="docutils literal notranslate"><span class="pre">a*</span></code> 中一样，最终的动作就是消耗尽可能多的模式。 当你尝试匹配一对对称分隔符，例如 HTML 标记周围的尖括号时，这个事实经常会让你感到困惑。因为 <code class="docutils literal notranslate"><span class="pre">.*</span></code> 的贪婪性质， 用于匹配单个 HTML 标记的简单模式不起作用。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">s</span> <span class="o">=</span> <span class="s1">&#39;&lt;html&gt;&lt;head&gt;&lt;title&gt;Title&lt;/title&gt;&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="go">32</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;&lt;.*&gt;&#39;</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">span</span><span class="p">())</span>
<span class="go">(0, 32)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;&lt;.*&gt;&#39;</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">group</span><span class="p">())</span>
<span class="go">&lt;html&gt;&lt;head&gt;&lt;title&gt;Title&lt;/title&gt;</span>
</pre></div>
</div>
<p>正则匹配 <code class="docutils literal notranslate"><span class="pre">'&lt;'</span></code> 中的 <code class="docutils literal notranslate"><span class="pre">'&lt;html&gt;'</span></code> 和 <code class="docutils literal notranslate"><span class="pre">.*</span></code> 消耗字符串的其余部分。 正则中还有更多的剩余东西，并且 <code class="docutils literal notranslate"><span class="pre">&gt;</span></code> 在字符串的末尾不能匹配，所以正则表达式引擎必须逐个字符地回溯，直到它找到匹配 <code class="docutils literal notranslate"><span class="pre">&gt;</span></code> 。最终匹配从 <code class="docutils literal notranslate"><span class="pre">'&lt;html&gt;'</span></code> 中的 <code class="docutils literal notranslate"><span class="pre">'&lt;'</span></code> 扩展到 <code class="docutils literal notranslate"><span class="pre">'&lt;/title&gt;'</span></code> 中的 <code class="docutils literal notranslate"><span class="pre">'&gt;'</span></code> ，而这并不是你想要的结果。</p>
<p>在这种情况下，解决方案是使用非贪婪的限定符 <code class="docutils literal notranslate"><span class="pre">*?</span></code> 、 <code class="docutils literal notranslate"><span class="pre">+?</span></code> 、 <code class="docutils literal notranslate"><span class="pre">??</span></code> 或 <code class="docutils literal notranslate"><span class="pre">{m,n}?</span></code> ，匹配为尽可能 <em>少</em> 的文字。 在上面的例子中，在第一次 <code class="docutils literal notranslate"><span class="pre">'&lt;'</span></code> 匹配后立即尝试 <code class="docutils literal notranslate"><span class="pre">'&gt;'</span></code> ，当它失败时，引擎一次前进一个字符，每一步都重试 <code class="docutils literal notranslate"><span class="pre">'&gt;'</span></code> 。 这产生了正确的结果:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">&#39;&lt;.*?&gt;&#39;</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span><span class="o">.</span><span class="n">group</span><span class="p">())</span>
<span class="go">&lt;html&gt;</span>
</pre></div>
</div>
<p>（请注意，使用正则表达式解析 HTML 或 XML 很痛苦。快而脏的模式将处理常见情况，但 HTML 和 XML 有特殊情况会破坏明显的正则表达式；当你编写正则表达式处理所有可能的情况时，模式将非常复杂。使用 HTML 或 XML 解析器模块来执行此类任务。）</p>
</div>
<div class="section" id="using-re-verbose">
<h3>使用 re.VERBOSE<a class="headerlink" href="#using-re-verbose" title="永久链接至标题">¶</a></h3>
<p>到目前为止，你可能已经注意到正则表达式是一种非常紧凑的表示法，但它们并不是非常易读。 具有中等复杂度的正则可能会成为反斜杠、括号和元字符的冗长集合，使其难以阅读和理解。</p>
<p>对于这样的正则，在编译正则表达式时指定 <a class="reference internal" href="../library/re.html#re.VERBOSE" title="re.VERBOSE"><code class="xref py py-const docutils literal notranslate"><span class="pre">re.VERBOSE</span></code></a> 标志可能会有所帮助，因为它允许你更清楚地格式化正则表达式。</p>
<p><code class="docutils literal notranslate"><span class="pre">re.VERBOSE</span></code> 标志有几种效果。 正则表达式中的 <em>不是</em> 在字符类中的空格将被忽略。 这意味着表达式如 <code class="docutils literal notranslate"><span class="pre">dog</span> <span class="pre">|</span> <span class="pre">cat</span></code> 等同于不太可读的 <code class="docutils literal notranslate"><span class="pre">dog|cat</span></code> ，但 <code class="docutils literal notranslate"><span class="pre">[a</span> <span class="pre">b]</span></code> 仍将匹配字符 <code class="docutils literal notranslate"><span class="pre">'a'</span></code> 、 <code class="docutils literal notranslate"><span class="pre">'b'</span></code> 或空格。 此外，你还可以在正则中放置注释；注释从 <code class="docutils literal notranslate"><span class="pre">#</span></code> 字符扩展到下一个换行符。 当与三引号字符串一起使用时，这使正则的格式更加整齐:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">pat</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> \s*                 # Skip leading whitespace</span>
<span class="s2"> (?P&lt;header&gt;[^:]+)   # Header name</span>
<span class="s2"> \s* :               # Whitespace, and a colon</span>
<span class="s2"> (?P&lt;value&gt;.*?)      # The header&#39;s value -- *? used to</span>
<span class="s2">                     # lose the following trailing whitespace</span>
<span class="s2"> \s*$                # Trailing whitespace to end-of-line</span>
<span class="s2">&quot;&quot;&quot;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span><span class="p">)</span>
</pre></div>
</div>
<p>这更具有可读性:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">pat</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;\s*(?P&lt;header&gt;[^:]+)\s*:(?P&lt;value&gt;.*?)\s*$&quot;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="feedback">
<h2>反馈<a class="headerlink" href="#feedback" title="永久链接至标题">¶</a></h2>
<p>正则表达式是一个复杂的主题。 这份文档是否有助于你理解它们？ 是否存在不清楚的部分，或者你遇到的问题未在此处涉及？ 如果是，请向作者发送改进建议。</p>
<p>关于正则表达式的最完整的书几乎肯定是由 O'Reilly 出版的 Jeffrey Friedl 的 Mastering Regular Expressions 。 不幸的是，它专注于 Perl 和 Java 的正则表达式，并且根本不包含任何 Python 材料，因此它不能用作 Python 编程的参考。 （第一版涵盖了 Python 现在删除的 <code class="xref py py-mod docutils literal notranslate"><span class="pre">regex</span></code> 模块，这对你没有多大帮助。）考虑从你的图书馆中查找它。</p>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">正则表达式HOWTO</a><ul>
<li><a class="reference internal" href="#introduction">概述</a></li>
<li><a class="reference internal" href="#simple-patterns">简单模式</a><ul>
<li><a class="reference internal" href="#matching-characters">匹配字符</a></li>
<li><a class="reference internal" href="#repeating-things">重复</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-regular-expressions">使用正则表达式</a><ul>
<li><a class="reference internal" href="#compiling-regular-expressions">编译正则表达式</a></li>
<li><a class="reference internal" href="#the-backslash-plague">反斜杠灾难</a></li>
<li><a class="reference internal" href="#performing-matches">应用匹配</a></li>
<li><a class="reference internal" href="#module-level-functions">模块级别函数</a></li>
<li><a class="reference internal" href="#compilation-flags">编译标志</a></li>
</ul>
</li>
<li><a class="reference internal" href="#more-pattern-power">更多模式能力</a><ul>
<li><a class="reference internal" href="#more-metacharacters">更多元字符</a></li>
<li><a class="reference internal" href="#grouping">分组</a></li>
<li><a class="reference internal" href="#non-capturing-and-named-groups">非捕获和命名组</a></li>
<li><a class="reference internal" href="#lookahead-assertions">前向断言</a></li>
</ul>
</li>
<li><a class="reference internal" href="#modifying-strings">修改字符串</a><ul>
<li><a class="reference internal" href="#splitting-strings">分割字符串</a></li>
<li><a class="reference internal" href="#search-and-replace">搜索和替换</a></li>
</ul>
</li>
<li><a class="reference internal" href="#common-problems">常见问题</a><ul>
<li><a class="reference internal" href="#use-string-methods">使用字符串方法</a></li>
<li><a class="reference internal" href="#match-versus-search">match() 和 search()</a></li>
<li><a class="reference internal" href="#greedy-versus-non-greedy">贪婪与非贪婪</a></li>
<li><a class="reference internal" href="#using-re-verbose">使用 re.VERBOSE</a></li>
</ul>
</li>
<li><a class="reference internal" href="#feedback">反馈</a></li>
</ul>
</li>
</ul>

  <h4>上一个主题</h4>
  <p class="topless"><a href="logging-cookbook.html"
                        title="上一章">日志操作手册</a></p>
  <h4>下一个主题</h4>
  <p class="topless"><a href="sockets.html"
                        title="下一章">套接字编程指南</a></p>
  <div role="note" aria-label="source link">
    <h3>本页</h3>
    <ul class="this-page-menu">
      <li><a href="../bugs.html">提交 Bug</a></li>
      <li>
        <a href="https://github.com/python/cpython/blob/3.7/Doc/howto/regex.rst"
            rel="nofollow">显示源代码
        </a>
      </li>
    </ul>
  </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             >索引</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python 模块索引"
             >模块</a> |</li>
        <li class="right" >
          <a href="sockets.html" title="套接字编程指南"
             >下一页</a> |</li>
        <li class="right" >
          <a href="logging-cookbook.html" title="日志操作手册"
             >上一页</a> |</li>
        <li><img src="../_static/py.png" alt=""
                 style="vertical-align: middle; margin-top: -1px"/></li>
        <li><a href="https://www.python.org/">Python</a> &#187;</li>
        <li>
          <span class="language_switcher_placeholder">zh_CN</span>
          <span class="version_switcher_placeholder">3.7.3</span>
          <a href="../index.html">文档</a> &#187;
        </li>

          <li class="nav-item nav-item-1"><a href="index.html" >Python 常用指引</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="快速搜索" type="text" name="q" />
          <input type="submit" value="转向" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>  
    <div class="footer">
    &copy; <a href="../copyright.html">版权所有</a> 2001-2019, Python Software Foundation.
    <br />
    Python 软件基金会是一个非盈利组织。
    <a href="https://www.python.org/psf/donations/">请捐助。</a>
    <br />
    最后更新于 4月 09, 2019.
    <a href="../bugs.html">发现了问题</a>？
    <br />
    使用<a href="http://sphinx.pocoo.org/">Sphinx</a>1.8.4 创建。
    </div>

  </body>
</html>